summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiam P. White <inkscapebronyat-signgmaildotcom>2014-03-12 12:56:04 +0000
committerLiam P. White <inkscapebronyat-signgmaildotcom>2014-03-12 12:56:04 +0000
commit13c192e2fa564c0a743e13e30b1cf6de9b1a39a6 (patch)
tree3e2b6a003977c53609cac33d16abf38de4954c5f /src
parentUpdate to trunk (diff)
downloadinkscape-13c192e2fa564c0a743e13e30b1cf6de9b1a39a6.tar.gz
inkscape-13c192e2fa564c0a743e13e30b1cf6de9b1a39a6.zip
Reverted swatches
Removed a toy effect (not ready yet) Fixed a bug with Livarot General cleanup (bzr r13090.1.23)
Diffstat (limited to 'src')
-rw-r--r--src/display/drawing-item.cpp5
-rw-r--r--src/live_effects/Makefile_insert4
-rw-r--r--src/live_effects/effect-enum.h2
-rw-r--r--src/live_effects/effect.cpp10
-rwxr-xr-xsrc/live_effects/lpe-jointype.h43
-rw-r--r--src/live_effects/parameter/originalpatharray.cpp7
-rwxr-xr-xsrc/live_effects/pathoutlineprovider.h766
-rw-r--r--src/path-chemistry.cpp8
-rw-r--r--src/splivarot.cpp28
-rw-r--r--src/ui/dialog/color-item.cpp862
-rw-r--r--src/ui/dialog/color-item.h108
-rw-r--r--src/ui/dialog/object-properties.cpp1
-rw-r--r--src/ui/dialog/objects.cpp227
-rw-r--r--src/ui/dialog/swatches.cpp2916
-rw-r--r--src/ui/dialog/swatches.h153
-rw-r--r--src/widgets/desktop-widget.cpp2
16 files changed, 1856 insertions, 3286 deletions
diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp
index 13e7b61eb..6c7f99d42 100644
--- a/src/display/drawing-item.cpp
+++ b/src/display/drawing-item.cpp
@@ -808,9 +808,10 @@ DrawingItem::pick(Geom::Point const &p, double delta, unsigned flags)
{
// Sometimes there's no BBOX in state, reason unknown (bug 992817)
// I made this not an assert to remove the warning
+ // This warning clutters the console output, so commented out
if (!(_state & STATE_BBOX) || !(_state & STATE_PICK)) {
- g_warning("Invalid state when picking: STATE_BBOX = %d, STATE_PICK = %d",
- _state & STATE_BBOX, _state & STATE_PICK);
+ /*g_warning("Invalid state when picking: STATE_BBOX = %d, STATE_PICK = %d",
+ _state & STATE_BBOX, _state & STATE_PICK);*/
return NULL;
}
// ignore invisible and insensitive items unless sticky
diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert
index 76d7b418f..35a85b4aa 100644
--- a/src/live_effects/Makefile_insert
+++ b/src/live_effects/Makefile_insert
@@ -92,6 +92,4 @@ ink_common_sources += \
live_effects/lpe-fill-between-many.cpp \
live_effects/lpe-fill-between-many.h \
live_effects/lpe-ellipse_5pts.cpp \
- live_effects/lpe-ellipse_5pts.h \
- live_effects/lpe-jointype.cpp \
- live_effects/lpe-jointype.h
+ live_effects/lpe-ellipse_5pts.h
diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h
index 46bc56a81..9c76875e9 100644
--- a/src/live_effects/effect-enum.h
+++ b/src/live_effects/effect-enum.h
@@ -55,7 +55,7 @@ enum EffectType {
FILL_BETWEEN_MANY,
ELLIPSE_5PTS,
BOUNDING_BOX,
- JOIN_TYPE,
+// JOIN_TYPE,
INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan)
};
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp
index 17b229352..eac0f79f4 100644
--- a/src/live_effects/effect.cpp
+++ b/src/live_effects/effect.cpp
@@ -5,7 +5,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#define LPE_ENABLE_TEST_EFFECTS
+//#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -52,7 +52,7 @@
#include "live_effects/lpe-fill-between-many.h"
#include "live_effects/lpe-ellipse_5pts.h"
#include "live_effects/lpe-bounding-box.h"
-#include "live_effects/lpe-jointype.h"
+//#include "live_effects/lpe-jointype.h"
#include "xml/node-event-vector.h"
#include "sp-object.h"
@@ -109,7 +109,7 @@ const Util::EnumData<EffectType> LPETypeData[] = {
{RECURSIVE_SKELETON, N_("Recursive skeleton"), "recursive_skeleton"},
{TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"},
{TEXT_LABEL, N_("Text label"), "text_label"},
- {JOIN_TYPE, N_("Join type"), "join_type"},
+// {JOIN_TYPE, N_("Join type"), "join_type"},
#endif
/* 0.46 */
{BEND_PATH, N_("Bend"), "bend_path"},
@@ -273,9 +273,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj)
case BOUNDING_BOX:
neweffect = static_cast<Effect*> ( new LPEBoundingBox(lpeobj) );
break;
- case JOIN_TYPE:
+ /*case JOIN_TYPE:
neweffect = static_cast<Effect*> ( new LPEJoinType(lpeobj) );
- break;
+ break;*/
default:
g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
neweffect = NULL;
diff --git a/src/live_effects/lpe-jointype.h b/src/live_effects/lpe-jointype.h
deleted file mode 100755
index db113c66a..000000000
--- a/src/live_effects/lpe-jointype.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Authors:
- * Liam P White
- *
- * Copyright (C) 2014 Authors
- *
- * Released under GNU GPL v2, read the file COPYING for more information
- */
-#ifndef INKSCAPE_LPE_JOINTYPE_H
-#define INKSCAPE_LPE_JOINTYPE_H
-
-#include "live_effects/effect.h"
-#include "live_effects/parameter/parameter.h"
-#include "live_effects/parameter/point.h"
-#include "live_effects/parameter/enum.h"
-
-namespace Inkscape {
-namespace LivePathEffect {
-
-class LPEJoinType : public Effect {
-public:
- LPEJoinType(LivePathEffectObject *lpeobject);
- virtual ~LPEJoinType();
-
- virtual void doOnApply(SPLPEItem const* lpeitem);
- virtual void doOnRemove(SPLPEItem const* lpeitem);
- virtual std::vector <Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
-
-private:
- LPEJoinType(const LPEJoinType&);
- LPEJoinType& operator=(const LPEJoinType&);
-
- ScalarParam line_width;
- EnumParam<unsigned> linecap_type;
- EnumParam<unsigned> linejoin_type;
- ScalarParam miter_limit;
- BoolParam attempt_force_join;
- bool was_initialized;
-};
-
-} //namespace LivePathEffect
-} //namespace Inkscape
-
-#endif
diff --git a/src/live_effects/parameter/originalpatharray.cpp b/src/live_effects/parameter/originalpatharray.cpp
index ed47db28d..514c9e23e 100644
--- a/src/live_effects/parameter/originalpatharray.cpp
+++ b/src/live_effects/parameter/originalpatharray.cpp
@@ -18,6 +18,7 @@
#include <gtkmm/icontheme.h>
#include <gtkmm/imagemenuitem.h>
#include <gtkmm/separatormenuitem.h>
+#include <gtkmm/scrolledwindow.h>
#include <glibmm/i18n.h>
@@ -31,7 +32,6 @@
#include "uri.h"
#include "display/curve.h"
-#include <glibmm/i18n.h>
#include <2geom/coord.h>
#include <2geom/point.h>
#include "sp-shape.h"
@@ -97,8 +97,9 @@ OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label,
_toggle_renderer->signal_toggled().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_reverse_toggled));
col->add_attribute(_toggle_renderer->property_active(), _model->_colReverse);
- //quick little hack -- new versions of gtk did not give the item enough space
- _scroller.property_height_request() = 120;
+ //quick little hack -- newer versions of gtk gave the item zero space allotment
+ _scroller.set_size_request(-1, 120);
+
_scroller.add(_tree);
_scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
//_scroller.set_shadow_type(Gtk::SHADOW_IN);
diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h
deleted file mode 100755
index 8aa2e38ad..000000000
--- a/src/live_effects/pathoutlineprovider.h
+++ /dev/null
@@ -1,766 +0,0 @@
-#pragma once
-
-#include <2geom/path.h>
-#include <2geom/circle.h>
-#include <2geom/sbasis-to-bezier.h>
-#include <2geom/shape.h>
-#include <2geom/transforms.h>
-#include <2geom/path-sink.h>
-
-#include <livarot/Path.h>
-#include <livarot/LivarotDefs.h>
-
-enum LineJoinType {
- LINEJOIN_STRAIGHT,
- LINEJOIN_ROUND,
- LINEJOIN_POINTY,
- LINEJOIN_REFLECTED,
- LINEJOIN_EXTRAPOLATED
-};
-
-namespace Geom
-{
- /**
- * Refer to: Weisstein, Eric W. "Circle-Circle Intersection."
- From MathWorld--A Wolfram Web Resource.
- http://mathworld.wolfram.com/Circle-CircleIntersection.html
- *
- * @return 0 if no intersection
- * @return 1 if one circle is contained in the other
- * @return 2 if intersections are found (they are written to p0 and p1)
- */
- static int circle_circle_intersection(Circle const &circle0, Circle const &circle1,
- Point & p0, Point & p1)
- {
- Point X0 = circle0.center();
- double r0 = circle0.ray();
- Point X1 = circle1.center();
- double r1 = circle1.ray();
-
- /* dx and dy are the vertical and horizontal distances between
- * the circle centers.
- */
- Point D = X1 - X0;
-
- /* Determine the straight-line distance between the centers. */
- double d = L2(D);
-
- /* Check for solvability. */
- if (d > (r0 + r1))
- {
- /* no solution. circles do not intersect. */
- return 0;
- }
- if (d <= fabs(r0 - r1))
- {
- /* no solution. one circle is contained in the other */
- return 1;
- }
-
- /* 'point 2' is the point where the line through the circle
- * intersection points crosses the line between the circle
- * centers.
- */
-
- /* Determine the distance from point 0 to point 2. */
- double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
-
- /* Determine the coordinates of point 2. */
- Point p2 = X0 + D * (a/d);
-
- /* Determine the distance from point 2 to either of the
- * intersection points.
- */
- double h = std::sqrt((r0*r0) - (a*a));
-
- /* Now determine the offsets of the intersection points from
- * point 2.
- */
- Point r = (h/d)*rot90(D);
-
- /* Determine the absolute intersection points. */
- p0 = p2 + r;
- p1 = p2 - r;
-
- return 2;
- }
- /**
- * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t.
- * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt).
- */
- static Circle touching_circle( D2<SBasis> const &curve, double t, double tol=0.01 )
- {
- D2<SBasis> dM=derivative(curve);
- if ( are_near(L2sq(dM(t)),0.) ) {
- dM=derivative(dM);
- }
- if ( are_near(L2sq(dM(t)),0.) ) { // try second time
- dM=derivative(dM);
- }
- Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
- Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
- Piecewise<SBasis> k = cross(derivative(unitv),unitv);
- k = divide(k,dMlength,tol,3);
- double curv = k(t); // note that this value is signed
-
- Geom::Point normal = unitTangentAt(curve, t).cw();
- double radius = 1/curv;
- Geom::Point center = curve(t) + radius*normal;
- return Geom::Circle(center, fabs(radius));
- }
-
- static std::vector<Geom::Path> split_at_cusps(const Geom::Path& in)
- {
- Geom::PathVector out = Geom::PathVector();
- Geom::Path temp = Geom::Path();
-
- for (unsigned path_descr = 0; path_descr < in.size(); path_descr++)
- {
- temp = Geom::Path();
- temp.append(in[path_descr]);
- out.push_back(temp);
- }
-
- return out;
- }
-
- static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2<Geom::SBasis> const & sbasis_in)
- {
- std::vector<Geom::Point> temp;
- sbasis_to_bezier(temp, sbasis_in, 4);
- return Geom::CubicBezier( temp );
- }
-
- static boost::optional<Geom::Point> intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a,
- Geom::Point const & origin_b, Geom::Point const & vector_b)
- {
- Geom::Coord denom = cross(vector_b, vector_a);
- if (!Geom::are_near(denom,0.)){
- Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom;
- return origin_a + t * vector_a;
- }
- return boost::none;
- }
-}
-
-namespace Outline
-{
-
- typedef Geom::D2<Geom::SBasis> D2SB;
- typedef Geom::Piecewise<D2SB> PWD2;
-
- static void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve*cbc2, Geom::Point endPt, double miter_limit)
-{
- Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2);
- if (cross.empty())
- {
- Geom::Path pth;
- pth.append(*cbc1);
-
- Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1);
-
- pth = Geom::Path();
- pth.append( *cbc2 );
- Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0);
-
-
- Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(cbc1->toSBasis()), 0.);
- Geom::Circle circle2 = Geom::touching_circle(cbc2->toSBasis(), 0);
-
- Geom::Point points[2];
- int solutions = Geom::circle_circle_intersection(circle1, circle2, points[0], points[1]);
- if (solutions == 2)
- {
- Geom::Point sol(0,0);
- if ( dot(tang2,points[0]-endPt) > 0 )
- {
- // points[0] is bad, choose points[1]
- sol = points[1];
- }
- else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1]
- // points[1] is bad, choose points[0]
- sol = points[0];
- }
- else
- {
- // both points are good, choose nearest
- sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ?
- points[0] : points[1];
- }
- Geom::EllipticalArc *arc0 = circle1.arc(cbc1->finalPoint(), 0.5*(cbc1->finalPoint()+sol), sol, true);
- Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true);
-
- if (arc0)
- {
- path_builder.append (arc0->toSBasis());
- delete arc0;
- arc0 = NULL;
- }
-
- if (arc1)
- {
- path_builder.append (arc1->toSBasis());
- delete arc1;
- arc1 = NULL;
- }
- }
- else
- {
- path_builder.appendNew<Geom::LineSegment> (endPt);
- }
- }
- else
- {
- path_builder.appendNew<Geom::LineSegment> (endPt);
- }
-}
- static Geom::Path half_outline_extrp(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit)
- {
- Geom::PathVector pv = split_at_cusps(path_in);
- unsigned m;
- Path path_outline = Path();
- Path path_tangent = Path();
-
- Geom::Point initialPoint;
- Geom::Point endPoint;
-
- Geom::Path path_builder = Geom::Path();
- Geom::PathVector * pathvec;
-
- //load the first portion in before the loop starts
- {
- path_outline = Path();
- path_outline.LoadPath(pv[0], Geom::Affine(), false, false);
- path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10);
- //now half of first cusp has been loaded
-
- pathvec = path_tangent.MakePathVector();
- path_tangent = Path();
-
- //instead of array accessing twice, dereferencing used for clarity
- initialPoint = (*pathvec)[0].initialPoint();
-
- path_builder.start(initialPoint);
- path_builder.append( (*pathvec)[0] );
-
- path_outline = Path();
- path_outline.LoadPath(pv[1], Geom::Affine(), false, false);
- path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10);
-
- delete pathvec; pathvec = NULL;
- pathvec = path_tangent.MakePathVector();
- path_tangent = Path();
-
- Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate();
- Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate();
-
- extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit );
-
- path_builder.append( (*pathvec)[0] );
-
- //always set pointers null after deleting
- delete pathvec; pathvec = NULL;
- delete cbc1; delete cbc2; cbc1 = cbc2 = NULL;
- }
-
- for (m = 2; m < pv.size(); m++)
- {
- path_outline = Path();
- path_outline.LoadPath(pv[m], Geom::Affine(), false, false);
- path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10);
-
- delete pathvec; pathvec = NULL;
- pathvec = path_tangent.MakePathVector();
-
- Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate();
- Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate();
-
- extrapolate_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit );
- path_builder.append( (*pathvec)[0] );
-
- delete pathvec; pathvec = NULL;
- delete cbc1; delete cbc2; cbc1 = cbc2 = NULL;
- }
-
- return path_builder;
- }
-
- //Create a reflected outline join.
- //Note: it is generally recommended to let half_outline do this for you!
- //path_builder: the path to append the curves to
- //cbc1: the curve before the join
- //cbc2: the curve after the join
- //endPt: the point to end at
- //miter_limit: the miter parameter
- static void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt, double miter_limit)
- {
- //the most important work for the reflected join is done here
-
- //determine where we are in the path. If we're on the inside, ignore
- //and just lineTo. On the outside, we'll do a little reflection magic :)
- Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2);
- if (cross.empty())
- {
- //probably on the outside of the corner
- Geom::Path pth;
- pth.append(*cbc1);
-
- Geom::Point tang1 = Geom::unitTangentAt(pth.toPwSb()[0], 1);
-
- //reflect curves along the bevel
- D2SB newcurve1 = pth.toPwSb()[0] *
- Geom::reflection ( -Geom::rot90(tang1) ,
- cbc1->finalPoint() );
-
- Geom::CubicBezier bzr1 = sbasis_to_cubicbezier(Geom::reverse(newcurve1));
-
- pth = Geom::Path();
- pth.append( *cbc2 );
- Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0);
-
- D2SB newcurve2 = pth.toPwSb()[0] *
- Geom::reflection ( -Geom::rot90(tang2) ,
- cbc2->initialPoint() );
- Geom::CubicBezier bzr2 = sbasis_to_cubicbezier(Geom::reverse(newcurve2));
-
- cross = Geom::crossings(bzr1, bzr2);
- if ( cross.empty() )
- {
- //std::cout << "Oops, no crossings!" << std::endl;
- //curves didn't cross; default to miter
- /*boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
- cbc2->initialPoint(), tang2);
- if (p)
- {
- path_builder.appendNew<Geom::LineSegment> (*p);
- }*/
- //bevel
- path_builder.appendNew<Geom::LineSegment>( endPt );
- }
- else
- {
- //join
- std::pair<Geom::CubicBezier, Geom::CubicBezier> sub1 = bzr1.subdivide(cross[0].ta);
- std::pair<Geom::CubicBezier, Geom::CubicBezier> sub2 = bzr2.subdivide(cross[0].tb);
-
- //@TODO joins have a strange tendency to cross themselves twice. Check this.
-
- //sections commented out are for general stability
- path_builder.appendNew <Geom::CubicBezier> (sub1.first[1], sub1.first[2], /*sub1.first[3]*/ sub2.second[0] );
- path_builder.appendNew <Geom::CubicBezier> (sub2.second[1], sub2.second[2], /*sub2.second[3]*/ endPt );
- }
- }
- else // cross.empty()
- {
- //probably on the inside of the corner
- path_builder.appendNew<Geom::LineSegment> ( endPt );
- }
- }
-
- /** @brief Converts a path to one half of an outline.
- * path_in: The input path to use. (To create the other side use path_in.reverse() )
- * line_width: the line width to use (usually you want to divide this by 2)
- * linecap_type: (not used here) the cap to apply. Passed to libvarot.
- * miter_limit: the miter parameter
- */
- static Geom::Path half_outline(const Geom::Path& path_in, double line_width, ButtType linecap_type, double miter_limit)
- {
- Geom::PathVector pv = split_at_cusps(path_in);
- unsigned m;
- Path path_outline = Path();
- Path path_tangent = Path();
- //needed for closing the path
- Geom::Point initialPoint;
- Geom::Point endPoint;
-
- //some issues prevented me from using a PathBuilder here
- //it seems like PathBuilder::peek() gave me a null reference exception
- //and I was unable to get a stack trace on Windows, so had to switch to Linux
- //to see what the hell was wrong. :(
- //I wasted five hours opening it in IDAPro, VS2012, and GDB Windows
-
- /*Program received signal SIGSEGV, Segmentation fault.
- 0x00000000006539ac in get_curves (this=0x0)
- at /usr/include/c++/4.6/bits/locale_facets.h:1077
- 1077 { return __c; }
- */
-
- Geom::Path path_builder = Geom::Path();
- Geom::PathVector * pathvec;
-
- //load the first portion in before the loop starts
- {
- path_outline = Path();
- path_outline.LoadPath(pv[0], Geom::Affine(), false, false);
- path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10);
- //now half of first cusp has been loaded
-
- pathvec = path_tangent.MakePathVector();
- path_tangent = Path();
-
- //instead of array accessing twice, dereferencing used for clarity
- initialPoint = (*pathvec)[0].initialPoint();
-
- path_builder.start(initialPoint);
- path_builder.append( (*pathvec)[0] );
-
- path_outline = Path();
- path_outline.LoadPath(pv[1], Geom::Affine(), false, false);
- path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10);
-
- delete pathvec; pathvec = NULL;
- pathvec = path_tangent.MakePathVector();
- path_tangent = Path();
-
- Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate();
- Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate();
-
- reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit );
-
- path_builder.append( (*pathvec)[0] );
-
- //always set pointers null after deleting
- delete pathvec; pathvec = NULL;
- delete cbc1; delete cbc2; cbc1 = cbc2 = NULL;
- }
-
- for (m = 2; m < pv.size(); m++)
- {
- path_outline = Path();
- path_outline.LoadPath(pv[m], Geom::Affine(), false, false);
- path_outline.OutsideOutline(&path_tangent, line_width / 2, join_straight, linecap_type, 10);
-
- delete pathvec; pathvec = NULL;
- pathvec = path_tangent.MakePathVector();
-
- Geom::Curve *cbc1 = path_builder[path_builder.size() - 1].duplicate();
- Geom::Curve *cbc2 = (*pathvec)[0][0].duplicate();
-
- reflect_curves(path_builder, cbc1, cbc2, (*pathvec)[0].initialPoint(), miter_limit );
- path_builder.append( (*pathvec)[0] );
-
- delete pathvec; pathvec = NULL;
- delete cbc1; delete cbc2; cbc1 = cbc2 = NULL;
- }
-
- return path_builder;
- }
-
- static Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, JoinType join, ButtType butt, double miter_lim)
- {
- Path p = Path();
- Path outlinepath = Path();
- for (unsigned i = 0; i < path_in.size(); i++)
- {
- p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true));
- }
-
- Geom::PathVector path_out;
- for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++)
- {
- if (path_in[lmnop].size() > 1)
- {
- Geom::Path p_init;
- Geom::Path p_rev;
- Geom::PathBuilder pb = Geom::PathBuilder();
-
- if ( !path_in[lmnop].closed() )
- {
- p_init = Outline::half_outline( path_in[lmnop], -line_width, butt,
- miter_lim );
- p_rev = Outline::half_outline( path_in[lmnop].reverse(), -line_width, butt,
- miter_lim );
-
- pb.moveTo(p_init.initialPoint() );
- pb.append(p_init);
-
- //cap
- if (butt == butt_straight) {
- pb.lineTo(p_rev.initialPoint() );
- } else if (butt == butt_round) {
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() );
- } else if (butt == butt_square) {
- //don't know what to do
- pb.lineTo(p_rev.initialPoint() );
- } else if (butt == butt_pointy) {
- //don't know what to do
- pb.lineTo(p_rev.initialPoint() );
- }
-
- pb.append(p_rev);
-
- if (butt == butt_straight) {
- pb.lineTo(p_init.initialPoint() );
- } else if (butt == butt_round) {
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() );
- } else if (butt == butt_square) {
- //don't know what to do
- pb.lineTo(p_init.initialPoint() );
- } else if (butt == butt_pointy) {
- //don't know what to do
- //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0);
- //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint());
-
- pb.lineTo(p_init.initialPoint() );
- }
- }
- else
- {
- //final join
- //refer to half_outline for documentation
- Geom::Path p_almost = path_in[lmnop];
- p_almost.appendNew<Geom::LineSegment> ( path_in[lmnop].initialPoint() );
- p_init = Outline::half_outline( p_almost, -line_width, butt,
- miter_lim );
- p_rev = Outline::half_outline( p_almost.reverse(), -line_width, butt,
- miter_lim );
- p.LoadPath(path_in[lmnop], Geom::Affine(), false, false);
-
- //this is a kludge, because I can't find how to make this work properly
- bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(),
- path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) ==
- (path_in[lmnop] [path_in[lmnop].size()].length()));
-
- p_almost = p_init;
- if (lastIsLinear)
- {
- p_almost.erase_last(); p_almost.erase_last();
- }
-
- //outside test
- Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate();
- Geom::Curve* cbc2 = p_almost[0].duplicate();
-
- Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2);
-
- if (cross.empty())
- {
- //this is the outside path
-
- //reuse the old one
- p_init = p_almost;
- Outline::reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim );
- pb.moveTo(p_init.initialPoint()); pb.append(p_init);
- }
- else
- {
- //inside, carry on :-)
- pb.moveTo(p_almost.initialPoint()); pb.append(p_almost);
- }
-
- p_almost = p_rev;
- if (lastIsLinear)
- {
- p_almost.erase(p_almost.begin() );
- p_almost.erase(p_almost.begin() );
- }
-
- delete cbc1; delete cbc2; cbc1 = cbc2 = NULL;
-
- cbc1 = p_almost[p_almost.size() - 1].duplicate();
- cbc2 = p_almost[0].duplicate();
-
- cross = Geom::crossings(*cbc1, *cbc2);
-
- if (cross.empty())
- {
- //outside path
-
- p_init = p_almost;
- reflect_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim );
- pb.moveTo(p_init.initialPoint()); pb.append(p_init);
- }
- else
- {
- //inside
- pb.moveTo(p_almost.initialPoint()); pb.append(p_almost);
- }
- delete cbc1; delete cbc2; cbc1 = cbc2 = NULL;
- }
- //pb.closePath();
- pb.flush();
- Geom::PathVector pv_np = pb.peek();
- //hack
- for (unsigned abcd = 0; abcd < pv_np.size(); abcd++)
- {
- path_out.push_back( pv_np[abcd] );
- }
- }
- else
- {
- p.LoadPath(path_in[lmnop], Geom::Affine(), false, false);
- p.Outline(&outlinepath, line_width / 2, join, butt, miter_lim);
- std::vector<Geom::Path> *pv_p = outlinepath.MakePathVector();
- //hack
- path_out.push_back( (*pv_p)[0].reverse() );
- delete pv_p;
- }
- }
- return path_out;
- }
- static Geom::PathVector outlinePath_extr(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtType butt, double miter_lim)
- {
- Path p = Path();
- Path outlinepath = Path();
- for (unsigned i = 0; i < path_in.size(); i++)
- {
- p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true));
- }
-
- Geom::PathVector path_out;
- for (unsigned lmnop = 0; lmnop < path_in.size(); lmnop++)
- {
- if (path_in[lmnop].size() > 1)
- {
- Geom::Path p_init;
- Geom::Path p_rev;
- Geom::PathBuilder pb = Geom::PathBuilder();
-
- if ( !path_in[lmnop].closed() )
- {
- p_init = Outline::half_outline_extrp( path_in[lmnop], -line_width, butt,
- miter_lim );
- p_rev = Outline::half_outline_extrp( path_in[lmnop].reverse(), -line_width, butt,
- miter_lim );
-
- pb.moveTo(p_init.initialPoint() );
- pb.append(p_init);
-
- //cap
- if (butt == butt_straight) {
- pb.lineTo(p_rev.initialPoint() );
- } else if (butt == butt_round) {
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_rev.initialPoint() );
- } else if (butt == butt_square) {
- //don't know what to do
- pb.lineTo(p_rev.initialPoint() );
- } else if (butt == butt_pointy) {
- //don't know what to do
- pb.lineTo(p_rev.initialPoint() );
- }
-
- pb.append(p_rev);
-
- if (butt == butt_straight) {
- pb.lineTo(p_init.initialPoint() );
- } else if (butt == butt_round) {
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, p_init.initialPoint() );
- } else if (butt == butt_square) {
- //don't know what to do
- pb.lineTo(p_init.initialPoint() );
- } else if (butt == butt_pointy) {
- //don't know what to do
- //Geom::Point end_deriv = Geom::unitTangentAt( Geom::reverse(path_in[lmnop].toPwSb()[path_in[lmnop].size()]), 0);
- //double radius = 0.5 * Geom::distance(path_in[lmnop].finalPoint(), p_rev.initialPoint());
-
- pb.lineTo(p_init.initialPoint() );
- }
- }
- else
- {
- //final join
- //refer to half_outline for documentation
- Geom::Path p_almost = path_in[lmnop];
- p_almost.appendNew<Geom::LineSegment> ( path_in[lmnop].initialPoint() );
- p_init = Outline::half_outline_extrp( p_almost, -line_width, butt,
- miter_lim );
- p_rev = Outline::half_outline_extrp( p_almost.reverse(), -line_width, butt,
- miter_lim );
- p.LoadPath(path_in[lmnop], Geom::Affine(), false, false);
-
- //this is a kludge, because I can't find how to make this work properly
- bool lastIsLinear = ( (Geom::distance(path_in[lmnop].finalPoint(),
- path_in[lmnop] [path_in[lmnop].size() - 1].finalPoint())) ==
- (path_in[lmnop] [path_in[lmnop].size()].length()));
-
- p_almost = p_init;
- if (lastIsLinear)
- {
- p_almost.erase_last(); p_almost.erase_last();
- }
-
- //outside test
- Geom::Curve* cbc1 = p_almost[p_almost.size() - 1].duplicate();
- Geom::Curve* cbc2 = p_almost[0].duplicate();
-
- Geom::Crossings cross = Geom::crossings(*cbc1, *cbc2);
-
- if (cross.empty())
- {
- //this is the outside path
-
- //reuse the old one
- p_init = p_almost;
- Outline::extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim );
- pb.moveTo(p_init.initialPoint()); pb.append(p_init);
- }
- else
- {
- //inside, carry on :-)
- pb.moveTo(p_almost.initialPoint()); pb.append(p_almost);
- }
-
- p_almost = p_rev;
- if (lastIsLinear)
- {
- p_almost.erase(p_almost.begin() );
- p_almost.erase(p_almost.begin() );
- }
-
- delete cbc1; delete cbc2; cbc1 = cbc2 = NULL;
-
- cbc1 = p_almost[p_almost.size() - 1].duplicate();
- cbc2 = p_almost[0].duplicate();
-
- cross = Geom::crossings(*cbc1, *cbc2);
-
- if (cross.empty())
- {
- //outside path
-
- p_init = p_almost;
- extrapolate_curves(p_init, cbc1, cbc2, p_almost.initialPoint(), miter_lim );
- pb.moveTo(p_init.initialPoint()); pb.append(p_init);
- }
- else
- {
- //inside
- pb.moveTo(p_almost.initialPoint()); pb.append(p_almost);
- }
- delete cbc1; delete cbc2; cbc1 = cbc2 = NULL;
- }
- //pb.closePath();
- pb.flush();
- Geom::PathVector pv_np = pb.peek();
- //hack
- for (unsigned abcd = 0; abcd < pv_np.size(); abcd++)
- {
- path_out.push_back( pv_np[abcd] );
- }
- }
- else
- {
- p.LoadPath(path_in[lmnop], Geom::Affine(), false, false);
- p.Outline(&outlinepath, line_width / 2, join_pointy, butt, miter_lim);
- std::vector<Geom::Path> *pv_p = outlinepath.MakePathVector();
- //hack
- path_out.push_back( (*pv_p)[0].reverse() );
- delete pv_p;
- }
- }
- return path_out;
- }
-
-
-} // namespace Outline
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/path-chemistry.cpp b/src/path-chemistry.cpp
index 5f478435d..456af3731 100644
--- a/src/path-chemistry.cpp
+++ b/src/path-chemistry.cpp
@@ -22,6 +22,7 @@
#include "xml/repr.h"
#include "svg/svg.h"
#include "display/curve.h"
+#include "color.h"
#include <glib.h>
#include <glibmm/i18n.h>
#include "sp-path.h"
@@ -438,6 +439,10 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec
gchar *title = item->title();
// remember description
gchar *desc = item->desc();
+ // remember highlight color
+ guint32 highlight_color = 0;
+ if (item->isHighlightSet())
+ highlight_color = item->highlight_color();
// It's going to resurrect, so we delete without notifying listeners.
item->deleteObject(false);
@@ -455,6 +460,9 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec
newObj->setDesc(desc);
g_free(desc);
}
+ if (highlight_color && newObj) {
+ SP_ITEM(newObj)->setHighlightColor( highlight_color );
+ }
// move to the saved position
repr->setPosition(pos > 0 ? pos : 0);
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index 5c7b389ff..1eab73b62 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -1339,6 +1339,10 @@ sp_selected_path_outline(SPDesktop *desktop)
gchar *title = item->title();
// remember description
gchar *desc = item->desc();
+ // remember highlight color
+ guint32 highlight_color = 0;
+ if (item->isHighlightSet())
+ highlight_color = item->highlight_color();
if (res->descr_cmd.size() > 1) { // if there's 0 or 1 node left, drop this path altogether
@@ -1381,6 +1385,9 @@ sp_selected_path_outline(SPDesktop *desktop)
if (desc) {
newitem->setDesc(desc);
}
+ if (highlight_color && newitem) {
+ newitem->setHighlightColor( highlight_color );
+ }
SPShape *shape = SP_SHAPE(item);
@@ -1456,13 +1463,23 @@ sp_selected_path_outline(SPDesktop *desktop)
g_repr, xml_doc, doc );
}
}
+ //bug 1290573: completely destroy the old object first to prevent
+ //an ID clash, which has issues on undo
+ curve->unref();
+ selection->remove(item);
+ item->deleteObject(false);
selection->add(g_repr);
Inkscape::GC::release(g_repr);
-
- } else {
+ } else
+ {
+ //bug 1290573: completely destroy the old object first to prevent
+ //an ID clash, which has issues on undo
+ curve->unref();
+ selection->remove(item);
+ item->deleteObject(false);
// add the new repr to the parent
parent->appendChild(repr);
@@ -1481,6 +1498,9 @@ sp_selected_path_outline(SPDesktop *desktop)
if (desc) {
newitem->setDesc(desc);
}
+ if (highlight_color && newitem) {
+ newitem->setHighlightColor( highlight_color );
+ }
selection->add(repr);
@@ -1488,10 +1508,6 @@ sp_selected_path_outline(SPDesktop *desktop)
Inkscape::GC::release(repr);
- curve->unref();
- selection->remove(item);
- item->deleteObject(false);
-
}
if (title) {
g_free(title);
diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp
index a1951ec48..bab7e18e1 100644
--- a/src/ui/dialog/color-item.cpp
+++ b/src/ui/dialog/color-item.cpp
@@ -11,8 +11,18 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include <errno.h>
+
+#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
+#include <glibmm/threads.h>
+#endif
+
#include <gtkmm/label.h>
+#include <glibmm/i18n.h>
#include <cairo.h>
#include <gtk/gtk.h>
@@ -35,216 +45,766 @@
#include "xml/repr.h"
#include "verbs.h"
#include "widgets/gradient-vector.h"
-#include "sp-paint-server.h"
#include "color.h" // for SP_RGBA32_U_COMPOSE
-#include <glibmm/i18n.h>
namespace Inkscape {
namespace UI {
namespace Dialogs {
+static std::vector<std::string> mimeStrings;
+static std::map<std::string, guint> mimeToInt;
+
-bool ColorItem::on_enter_notify_event(GdkEventCrossing* event)
+#if ENABLE_MAGIC_COLORS
+// TODO remove this soon:
+extern std::vector<SwatchPage*> possible;
+#endif // ENABLE_MAGIC_COLORS
+
+
+#if ENABLE_MAGIC_COLORS
+static bool bruteForce( SPDocument* document, Inkscape::XML::Node* node, Glib::ustring const& match, int r, int g, int b )
{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if ( desktop ) {
- gchar* msg = g_strdup_printf(_("Color: <b>%s</b>; <b>Click</b> to set fill, <b>Shift+click</b> to set stroke"),def);
- desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg);
- g_free(msg);
+ bool changed = false;
+
+ if ( node ) {
+ gchar const * val = node->attribute("inkscape:x-fill-tag");
+ if ( val && (match == val) ) {
+ SPObject *obj = document->getObjectByRepr( node );
+
+ gchar c[64] = {0};
+ sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) );
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property( css, "fill", c );
+
+ sp_desktop_apply_css_recursive( obj, css, true );
+ static_cast<SPItem*>(obj)->updateRepr();
+
+ changed = true;
+ }
+
+ val = node->attribute("inkscape:x-stroke-tag");
+ if ( val && (match == val) ) {
+ SPObject *obj = document->getObjectByRepr( node );
+
+ gchar c[64] = {0};
+ sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) );
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property( css, "stroke", c );
+
+ sp_desktop_apply_css_recursive( (SPItem*)obj, css, true );
+ ((SPItem*)obj)->updateRepr();
+
+ changed = true;
+ }
+
+ Inkscape::XML::Node* first = node->firstChild();
+ changed |= bruteForce( document, first, match, r, g, b );
+
+ changed |= bruteForce( document, node->next(), match, r, g, b );
}
- return Gtk::Widget::on_enter_notify_event(event);
+
+ return changed;
+}
+#endif // ENABLE_MAGIC_COLORS
+
+static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ item->buttonClicked(false);
+ }
+}
+
+static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ item->buttonClicked(true);
+ }
+}
+
+static gboolean handleEnterNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if ( desktop ) {
+ gchar* msg = g_strdup_printf(_("Color: <b>%s</b>; <b>Click</b> to set fill, <b>Shift+click</b> to set stroke"),
+ item->def.descr.c_str());
+ desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg);
+ g_free(msg);
+ }
+ }
+ return FALSE;
+}
+
+static gboolean handleLeaveNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if ( desktop ) {
+ desktop->tipsMessageContext()->clear();
+ }
+ }
+ return FALSE;
}
-bool ColorItem::on_leave_notify_event(GdkEventCrossing* event)
+static void dieDieDie( GObject *obj, gpointer user_data )
{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if ( desktop ) {
- desktop->tipsMessageContext()->clear();
+ g_message("die die die %p %p", obj, user_data );
+}
+
+static bool getBlock( std::string& dst, guchar ch, std::string const & str )
+{
+ bool good = false;
+ std::string::size_type pos = str.find(ch);
+ if ( pos != std::string::npos )
+ {
+ std::string::size_type pos2 = str.find( '(', pos );
+ if ( pos2 != std::string::npos ) {
+ std::string::size_type endPos = str.find( ')', pos2 );
+ if ( endPos != std::string::npos ) {
+ dst = str.substr( pos2 + 1, (endPos - pos2 - 1) );
+ good = true;
+ }
+ }
}
- return Gtk::Widget::on_leave_notify_event(event);
+ return good;
}
-void ColorItem::selection_modified(Selection* selection, guint flags)
+static bool popVal( guint64& numVal, std::string& str )
{
- selection_changed(selection);
+ bool good = false;
+ std::string::size_type endPos = str.find(',');
+ if ( endPos == std::string::npos ) {
+ endPos = str.length();
+ }
+
+ if ( endPos != std::string::npos && endPos > 0 ) {
+ std::string xxx = str.substr( 0, endPos );
+ const gchar* ptr = xxx.c_str();
+ gchar* endPtr = 0;
+ numVal = g_ascii_strtoull( ptr, &endPtr, 10 );
+ if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) {
+ // overflow
+ } else if ( (numVal == 0) && (endPtr == ptr) ) {
+ // failed conversion
+ } else {
+ good = true;
+ str.erase( 0, endPos + 1 );
+ }
+ }
+
+ return good;
}
-void ColorItem::selection_changed(Selection* selection)
+// TODO resolve this more cleanly:
+extern gboolean colorItemHandleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event, gpointer user_data);
+
+static void colorItemDragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpointer data )
{
- SPItem* item = selection->singleItem();
- SPPaintServer* grad;
- if (item &&
- (
- (item->style->fill.isPaintserver() &&
- SP_IS_GRADIENT( (grad = item->style->getFillPaintServer()) )
- && SP_GRADIENT(grad)->getVector() == gradient) ||
-
- (item->style->stroke.isPaintserver() &&
- SP_IS_GRADIENT( (grad = item->style->getStrokePaintServer()) ) &&
- SP_GRADIENT(grad)->getVector() == gradient)
- )
- )
+ ColorItem* item = reinterpret_cast<ColorItem*>(data);
+ if ( item )
{
- if (!_isSelected) {
- _isSelected = true;
- queue_draw();
+ 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;
+ gsize bytesRead = 0;
+ gsize bytesWritten = 0;
+ gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"),
+ -1,
+ &bytesRead,
+ &bytesWritten,
+ &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 );
+ } else {
+ GdkPixbuf* pixbuf = 0;
+ if ( item->getGradient() ){
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+ cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(item->getGradient(), width);
+ cairo_t *ct = cairo_create(s);
+ cairo_set_source(ct, gradient);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+ cairo_pattern_destroy(gradient);
+ cairo_surface_flush(s);
+
+ pixbuf = ink_pixbuf_create_from_cairo_surface(s);
+ } else {
+ 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();
+ g_object_ref(G_OBJECT(pixbuf));
+ }
+ gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 );
}
- } else if (_isSelected) {
- _isSelected = false;
- queue_draw();
}
+
+}
+
+//"drag-drop"
+// gboolean dragDropColorData( GtkWidget *widget,
+// GdkDragContext *drag_context,
+// gint x,
+// gint y,
+// guint time,
+// gpointer user_data)
+// {
+// // TODO finish
+
+// return TRUE;
+// }
+
+
+SwatchPage::SwatchPage()
+ : _prefWidth(0)
+{
}
-ColorItem::ColorItem( SPGradient* grad, const gchar* name, SPDesktop* desktop ) :
- Glib::ObjectBase("coloritem"),
- Gtk::Widget(),
- def( name ),
- gradient(grad),
- _isSelected(false)
+SwatchPage::~SwatchPage()
{
- set_has_window(true);
- add_events(Gdk::BUTTON_PRESS_MASK);
- add_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
- sel_connection = desktop->selection->connectChanged(sigc::mem_fun(*this, &ColorItem::selection_changed));
- mod_connection = desktop->selection->connectModified(sigc::mem_fun(*this, &ColorItem::selection_modified));
- selection_changed(desktop->selection);
}
-void ColorItem::on_size_request(Gtk::Requisition* requisition)
+
+ColorItem::ColorItem(ege::PaintDef::ColorType type) :
+ def(type),
+ _isFill(false),
+ _isStroke(false),
+ _isLive(false),
+ _linkIsTone(false),
+ _linkPercent(0),
+ _linkGray(0),
+ _linkSrc(0),
+ _grad(0),
+ _pattern(0)
{
- requisition->height = 20;
- requisition->width = 20;
}
-void ColorItem::on_size_allocate(Gtk::Allocation& allocation)
+ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) :
+ def( r, g, b, name ),
+ _isFill(false),
+ _isStroke(false),
+ _isLive(false),
+ _linkIsTone(false),
+ _linkPercent(0),
+ _linkGray(0),
+ _linkSrc(0),
+ _grad(0),
+ _pattern(0)
{
- set_allocation(allocation);
- if (m_refGdkWindow)
- {
- m_refGdkWindow->move_resize( allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height() );
+}
+
+ColorItem::~ColorItem()
+{
+ if (_pattern != NULL) {
+ cairo_pattern_destroy(_pattern);
+ }
+}
+
+ColorItem::ColorItem(ColorItem const &other) :
+ Inkscape::UI::Previewable()
+{
+ if ( this != &other ) {
+ *this = other;
+ }
+}
+
+ColorItem &ColorItem::operator=(ColorItem const &other)
+{
+ if ( this != &other ) {
+ def = other.def;
+
+ // TODO - correct linkage
+ _linkSrc = other._linkSrc;
+ g_message("Erk!");
+ }
+ 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) );
+ }
+ }
+ }
+}
+
+void ColorItem::setGradient(SPGradient *grad)
+{
+ if (_grad != grad) {
+ _grad = grad;
+ // TODO regen and push to listeners
}
+
+ setName( gr_prepare_label(_grad) );
}
-void ColorItem::on_map()
+void ColorItem::setName(const Glib::ustring name)
{
- Gtk::Widget::on_map();
+ //def.descr = name;
+
+ for ( std::vector<Gtk::Widget*>::iterator it = _previews.begin(); it != _previews.end(); ++it ) {
+ Gtk::Widget* widget = *it;
+ if ( IS_EEK_PREVIEW(widget->gobj()) ) {
+ gtk_widget_set_tooltip_text(GTK_WIDGET(widget->gobj()), name.c_str());
+ }
+ else if ( GTK_IS_LABEL(widget->gobj()) ) {
+ gtk_label_set_text(GTK_LABEL(widget->gobj()), name.c_str());
+ }
+ }
}
-void ColorItem::on_unmap()
+void ColorItem::setPattern(cairo_pattern_t *pattern)
{
- Gtk::Widget::on_unmap();
+ if (pattern) {
+ cairo_pattern_reference(pattern);
+ }
+ if (_pattern) {
+ cairo_pattern_destroy(_pattern);
+ }
+ _pattern = pattern;
+
+ _updatePreviews();
}
-void ColorItem::on_realize()
+void ColorItem::_dragGetColorData( GtkWidget */*widget*/,
+ GdkDragContext */*drag_context*/,
+ GtkSelectionData *data,
+ guint info,
+ guint /*time*/,
+ gpointer user_data)
+{
+ ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
+ std::string key;
+ if ( info < mimeStrings.size() ) {
+ key = mimeStrings[info];
+ } else {
+ g_warning("ERROR: unknown value (%d)", info);
+ }
+
+ if ( !key.empty() ) {
+ char* tmp = 0;
+ int len = 0;
+ int format = 0;
+ item->def.getMIMEData(key, tmp, len, format);
+ if ( tmp ) {
+ GdkAtom dataAtom = gdk_atom_intern( key.c_str(), FALSE );
+ gtk_selection_data_set( data, dataAtom, format, (guchar*)tmp, len );
+ delete[] tmp;
+ }
+ }
+}
+
+void ColorItem::_dropDataIn( GtkWidget */*widget*/,
+ GdkDragContext */*drag_context*/,
+ gint /*x*/, gint /*y*/,
+ GtkSelectionData */*data*/,
+ guint /*info*/,
+ guint /*event_time*/,
+ gpointer /*user_data*/)
{
- set_realized();
- ensure_style();
-
- if(!m_refGdkWindow)
- {
- //Create the GdkWindow:
-
- GdkWindowAttr attributes;
- memset(&attributes, 0, sizeof(attributes));
-
- Gtk::Allocation allocation = get_allocation();
-
- //Set initial position and size of the Gdk::Window:
- attributes.x = allocation.get_x();
- attributes.y = allocation.get_y();
- attributes.width = allocation.get_width();
- attributes.height = allocation.get_height();
-
- attributes.event_mask = get_events () | Gdk::EXPOSURE_MASK;
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.wclass = GDK_INPUT_OUTPUT;
-
- m_refGdkWindow = Gdk::Window::create(get_parent_window(), &attributes,
- GDK_WA_X | GDK_WA_Y);
- set_window(m_refGdkWindow);
-
- //Attach this widget's style to its Gdk::Window.
- style_attach();
-
- //make the widget receive expose events
- m_refGdkWindow->set_user_data(gobj());
- }
}
-void ColorItem::on_unrealize()
+void ColorItem::_colorDefChanged(void* data)
{
- m_refGdkWindow.reset();
-
- Gtk::Widget::on_unrealize();
+ ColorItem* item = reinterpret_cast<ColorItem*>(data);
+ if ( item ) {
+ item->_updatePreviews();
+ }
}
-bool ColorItem::on_expose_event(GdkEventExpose* event)
+void ColorItem::_updatePreviews()
{
- if(m_refGdkWindow)
+ 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());
+
+ _regenPreview(preview);
+
+ widget->queue_draw();
+ }
+ }
+
+ for ( std::vector<ColorItem*>::iterator it = _listeners.begin(); it != _listeners.end(); ++it ) {
+ guint r = def.getR();
+ guint g = def.getG();
+ guint b = def.getB();
+
+ if ( (*it)->_linkIsTone ) {
+ r = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * r) ) / 100;
+ g = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * g) ) / 100;
+ b = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * b) ) / 100;
+ } else {
+ r = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * r) ) / 100;
+ g = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * g) ) / 100;
+ b = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * b) ) / 100;
+ }
+
+ (*it)->def.setRGB( r, g, b );
+ }
+
+
+#if ENABLE_MAGIC_COLORS
+ // Look for objects using this color
{
- Cairo::RefPtr<Cairo::Context> cr = m_refGdkWindow->create_cairo_context();
- if(event)
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if ( desktop ) {
+ SPDocument* document = sp_desktop_document( desktop );
+ Inkscape::XML::Node *rroot = document->getReprRoot();
+ if ( rroot ) {
+
+ // Find where this thing came from
+ Glib::ustring paletteName;
+ bool found = false;
+ int index = 0;
+ for ( std::vector<SwatchPage*>::iterator it2 = possible.begin(); it2 != possible.end() && !found; ++it2 ) {
+ SwatchPage* curr = *it2;
+ index = 0;
+ for ( boost::ptr_vector<ColorItem>::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) {
+ if ( this == &*zz ) {
+ found = true;
+ paletteName = curr->_name;
+ break;
+ } else {
+ index++;
+ }
+ }
+ }
+
+ if ( !paletteName.empty() ) {
+ gchar* str = g_strdup_printf("%d|", index);
+ paletteName.insert( 0, str );
+ g_free(str);
+ str = 0;
+
+ if ( bruteForce( document, rroot, paletteName, def.getR(), def.getG(), def.getB() ) ) {
+ SPDocumentUndo::done( document , SP_VERB_DIALOG_SWATCHES,
+ _("Change color definition"));
+ }
+ }
+ }
+ }
+ }
+#endif // ENABLE_MAGIC_COLORS
+
+}
+
+void ColorItem::_regenPreview(EekPreview * preview)
+{
+ if ( def.getType() != ege::PaintDef::RGB ) {
+ using Inkscape::IO::Resource::get_path;
+ using Inkscape::IO::Resource::ICONS;
+ using Inkscape::IO::Resource::SYSTEM;
+ GError *error = NULL;
+ gsize bytesRead = 0;
+ gsize bytesWritten = 0;
+ gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"),
+ -1,
+ &bytesRead,
+ &bytesWritten,
+ &error);
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(localFilename, &error);
+ if (!pixbuf) {
+ g_warning("Null pixbuf for %p [%s]", localFilename, localFilename );
+ }
+ g_free(localFilename);
+
+ eek_preview_set_pixbuf( preview, pixbuf );
+ }
+ else if ( !_pattern ){
+ eek_preview_set_color( preview,
+ (def.getR() << 8) | def.getR(),
+ (def.getG() << 8) | def.getG(),
+ (def.getB() << 8) | def.getB() );
+ } else {
+ // These correspond to PREVIEW_PIXBUF_WIDTH and VBLOCK from swatches.cpp
+ // TODO: the pattern to draw should be in the widget that draws the preview,
+ // so the preview can be scalable
+ int w = 128;
+ int h = 16;
+
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
+ cairo_t *ct = cairo_create(s);
+ cairo_set_source(ct, _pattern);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+ cairo_surface_flush(s);
+
+ GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s);
+ eek_preview_set_pixbuf( preview, pixbuf );
+ }
+
+ eek_preview_set_linked( preview, (LinkType)((_linkSrc ? PREVIEW_LINK_IN:0)
+ | (_listeners.empty() ? 0:PREVIEW_LINK_OUT)
+ | (_isLive ? PREVIEW_LINK_OTHER:0)) );
+}
+
+Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio, guint border)
+{
+ Gtk::Widget* widget = 0;
+ if ( style == PREVIEW_STYLE_BLURB) {
+ Gtk::Label *lbl = new Gtk::Label(def.descr);
+ lbl->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
+ widget = lbl;
+ } else {
+ GtkWidget* eekWidget = eek_preview_new();
+ EekPreview * preview = EEK_PREVIEW(eekWidget);
+ Gtk::Widget* newBlot = Glib::wrap(eekWidget);
+ _regenPreview(preview);
+
+ eek_preview_set_details( preview,
+ (::ViewType)view,
+ (::PreviewSize)size,
+ ratio,
+ border );
+
+ def.addCallback( _colorDefChanged, this );
+ eek_preview_set_focus_on_click(preview, FALSE);
+ newBlot->set_tooltip_text(def.descr);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "clicked",
+ G_CALLBACK(handleClick),
+ this);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "alt-clicked",
+ G_CALLBACK(handleSecondaryClick),
+ this);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "button-press-event",
+ G_CALLBACK(colorItemHandleButtonPress),
+ this);
+
{
- // clip to the area that needs to be re-exposed so we don't draw any
- // more than we need to.
- cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height);
- cr->clip();
+ std::vector<std::string> listing = def.getMIMETypes();
+ int entryCount = listing.size();
+ GtkTargetEntry* entries = new GtkTargetEntry[entryCount];
+ GtkTargetEntry* curr = entries;
+ for ( std::vector<std::string>::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++;
+ }
+ gtk_drag_source_set( GTK_WIDGET(newBlot->gobj()),
+ GDK_BUTTON1_MASK,
+ entries, entryCount,
+ GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY) );
+ for ( int i = 0; i < entryCount; i++ ) {
+ g_free(entries[i].target);
+ }
+ delete[] entries;
}
- if (gradient) {
- cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
-
- Cairo::RefPtr<Cairo::Pattern> checkpat(new Cairo::Pattern(check));
-
- cr->set_source(checkpat);
- cr->paint();
-
- cairo_pattern_t *g = sp_gradient_create_preview_pattern(gradient, get_allocation().get_width());
- Cairo::RefPtr<Cairo::Pattern> gpat(new Cairo::Pattern(g));
- cr->set_source(gpat);
- cr->paint();
- gpat.clear();
- cairo_pattern_destroy(g);
-
- checkpat.clear();
-
- cairo_pattern_destroy(check);
-
- if (_isSelected) {
- cr->set_source_rgb(0, 0, 0);
- cr->set_line_width(3);
- cr->move_to(0, get_allocation().get_height());
- cr->line_to(0,0);
- cr->line_to(get_allocation().get_width(), 0);
- cr->stroke();
- cr->move_to(get_allocation().get_width(), 0);
- cr->set_source_rgb(1, 1, 1);
- cr->line_to(get_allocation().get_width(), get_allocation().get_height());
- cr->line_to(0, get_allocation().get_height());
- //cr->rectangle(0, 0, get_allocation().get_width(), get_allocation().get_height());
- cr->stroke();
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "drag-data-get",
+ G_CALLBACK(ColorItem::_dragGetColorData),
+ this);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "drag-begin",
+ G_CALLBACK(colorItemDragBegin),
+ this );
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "enter-notify-event",
+ G_CALLBACK(handleEnterNotify),
+ this);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "leave-notify-event",
+ G_CALLBACK(handleLeaveNotify),
+ this);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "destroy",
+ G_CALLBACK(dieDieDie),
+ this);
+
+
+ widget = newBlot;
+ }
+
+ _previews.push_back( widget );
+
+ return widget;
+}
+
+void ColorItem::buttonClicked(bool secondary)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (desktop) {
+ char const * attrName = secondary ? "stroke" : "fill";
+
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ Glib::ustring descr;
+ switch (def.getType()) {
+ case ege::PaintDef::CLEAR: {
+ // TODO actually make this clear
+ sp_repr_css_set_property( css, attrName, "none" );
+ descr = secondary? _("Remove stroke color") : _("Remove fill color");
+ break;
+ }
+ case ege::PaintDef::NONE: {
+ sp_repr_css_set_property( css, attrName, "none" );
+ descr = secondary? _("Set stroke color to none") : _("Set fill color to none");
+ break;
+ }
+//mark
+ case ege::PaintDef::RGB: {
+ Glib::ustring colorspec;
+ if ( _grad ){
+ colorspec = "url(#";
+ colorspec += _grad->getId();
+ colorspec += ")";
+ } else {
+ 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;
+ }
+//end mark
+ sp_repr_css_set_property( css, attrName, colorspec.c_str() );
+ descr = secondary? _("Set stroke color from swatch") : _("Set fill color from swatch");
+ break;
}
- } else {
- cr->set_source_rgb(1, 1, 1);
- cr->paint();
- cr->set_source_rgb(1, 0, 0);
- cr->set_line_width(3);
- cr->move_to(0,0);
- cr->line_to(get_allocation().get_width(), get_allocation().get_height());
- cr->move_to(get_allocation().get_width(), 0);
- cr->line_to(0, get_allocation().get_height());
- cr->stroke();
}
+ sp_desktop_set_style(desktop, css);
+ sp_repr_css_attr_unref(css);
+
+ DocumentUndo::done( sp_desktop_document(desktop), SP_VERB_DIALOG_SWATCHES, descr.c_str() );
}
- return true;
}
-ColorItem::~ColorItem()
+void ColorItem::_wireMagicColors( SwatchPage *colorSet )
+{
+ if ( colorSet )
+ {
+ for ( boost::ptr_vector<ColorItem>::iterator it = colorSet->_colors.begin(); it != colorSet->_colors.end(); ++it )
+ {
+ std::string::size_type pos = it->def.descr.find("*{");
+ if ( pos != std::string::npos )
+ {
+ std::string subby = it->def.descr.substr( pos + 2 );
+ std::string::size_type endPos = subby.find("}*");
+ if ( endPos != std::string::npos )
+ {
+ subby.erase( endPos );
+ //g_message("FOUND MAGIC at '%s'", (*it)->def.descr.c_str());
+ //g_message(" '%s'", subby.c_str());
+
+ if ( subby.find('E') != std::string::npos )
+ {
+ it->def.setEditable( true );
+ }
+
+ if ( subby.find('L') != std::string::npos )
+ {
+ it->_isLive = true;
+ }
+
+ std::string part;
+ // Tint. index + 1 more val.
+ if ( getBlock( part, 'T', subby ) ) {
+ guint64 colorIndex = 0;
+ if ( popVal( colorIndex, part ) ) {
+ guint64 percent = 0;
+ if ( popVal( percent, part ) ) {
+ it->_linkTint( colorSet->_colors[colorIndex], percent );
+ }
+ }
+ }
+
+ // Shade/tone. index + 1 or 2 more val.
+ if ( getBlock( part, 'S', subby ) ) {
+ guint64 colorIndex = 0;
+ if ( popVal( colorIndex, part ) ) {
+ guint64 percent = 0;
+ if ( popVal( percent, part ) ) {
+ guint64 grayLevel = 0;
+ if ( !popVal( grayLevel, part ) ) {
+ grayLevel = 0;
+ }
+ it->_linkTone( colorSet->_colors[colorIndex], percent, grayLevel );
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+}
+
+
+void ColorItem::_linkTint( ColorItem& other, int percent )
+{
+ if ( !_linkSrc )
+ {
+ other._listeners.push_back(this);
+ _linkIsTone = false;
+ _linkPercent = percent;
+ if ( _linkPercent > 100 )
+ _linkPercent = 100;
+ if ( _linkPercent < 0 )
+ _linkPercent = 0;
+ _linkGray = 0;
+ _linkSrc = &other;
+
+ ColorItem::_colorDefChanged(&other);
+ }
+}
+
+void ColorItem::_linkTone( ColorItem& other, int percent, int grayLevel )
{
- sel_connection.disconnect();
- mod_connection.disconnect();
+ if ( !_linkSrc )
+ {
+ other._listeners.push_back(this);
+ _linkIsTone = true;
+ _linkPercent = percent;
+ if ( _linkPercent > 100 )
+ _linkPercent = 100;
+ if ( _linkPercent < 0 )
+ _linkPercent = 0;
+ _linkGray = grayLevel;
+ _linkSrc = &other;
+
+ ColorItem::_colorDefChanged(&other);
+ }
}
} // namespace Dialogs
diff --git a/src/ui/dialog/color-item.h b/src/ui/dialog/color-item.h
index 5d97d8803..3a0b33193 100644
--- a/src/ui/dialog/color-item.h
+++ b/src/ui/dialog/color-item.h
@@ -15,11 +15,7 @@
#include <boost/ptr_container/ptr_vector.hpp>
#include "widgets/ege-paint-def.h"
-#include "widgets/eek-preview.h"
-#include <gtk/gtk.h>
-#include <gtkmm/widget.h>
-#include "desktop.h"
-#include "selection.h"
+#include "ui/previewable.h"
class SPGradient;
@@ -27,43 +23,89 @@ namespace Inkscape {
namespace UI {
namespace Dialogs {
+class ColorItem;
+
+class SwatchPage
+{
+public:
+ SwatchPage();
+ ~SwatchPage();
+
+ Glib::ustring _name;
+ int _prefWidth;
+ boost::ptr_vector<ColorItem> _colors;
+};
+
/**
* The color swatch you see on screen as a clickable box.
*/
-class ColorItem : public Gtk::Widget
+class ColorItem : public Inkscape::UI::Previewable
{
+ friend void _loadPaletteFile( gchar const *filename );
public:
- ColorItem( SPGradient * grad, const gchar* name, SPDesktop* desktop );
+ ColorItem( ege::PaintDef::ColorType type );
+ ColorItem( unsigned int r, unsigned int g, unsigned int b,
+ Glib::ustring& name );
virtual ~ColorItem();
-
- SPGradient * getGradient() { return gradient; }
-
-protected:
-
- const gchar* def;
- SPGradient * gradient;
- virtual bool on_enter_notify_event(GdkEventCrossing* event);
- virtual bool on_leave_notify_event(GdkEventCrossing* event);
-
- virtual void on_size_request(Gtk::Requisition* requisition);
- virtual void on_size_allocate(Gtk::Allocation& allocation);
- virtual void on_map();
- virtual void on_unmap();
- virtual void on_realize();
- virtual void on_unrealize();
- virtual bool on_expose_event(GdkEventExpose* event);
-
- Glib::RefPtr<Gdk::Window> m_refGdkWindow;
-
-
+ ColorItem(ColorItem const &other);
+ virtual ColorItem &operator=(ColorItem const &other);
+ virtual Gtk::Widget* getPreview(PreviewStyle style,
+ ViewType view,
+ ::PreviewSize size,
+ guint ratio,
+ guint border);
+ void buttonClicked(bool secondary = false);
+
+ void setGradient(SPGradient *grad);
+ SPGradient * getGradient() const { return _grad; }
+ void setPattern(cairo_pattern_t *pattern);
+ void setName(const Glib::ustring name);
+
+ void setState( bool fill, bool stroke );
+ bool isFill() { return _isFill; }
+ bool isStroke() { return _isStroke; }
+
+ ege::PaintDef def;
+
private:
- void selection_changed(Selection* selection);
- void selection_modified(Selection* selection, guint flags);
- sigc::connection sel_connection;
- sigc::connection mod_connection;
- bool _isSelected;
+ 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( SwatchPage *colorSet );
+ static void _colorDefChanged(void* data);
+
+ void _updatePreviews();
+ void _regenPreview(EekPreview * preview);
+
+ void _linkTint( ColorItem& other, int percent );
+ void _linkTone( ColorItem& other, int percent, int grayLevel );
+
+ std::vector<Gtk::Widget*> _previews;
+
+ bool _isFill;
+ bool _isStroke;
+ bool _isLive;
+ bool _linkIsTone;
+ int _linkPercent;
+ int _linkGray;
+ ColorItem* _linkSrc;
+ SPGradient* _grad;
+ cairo_pattern_t *_pattern;
+ std::vector<ColorItem*> _listeners;
};
} // namespace Dialogs
diff --git a/src/ui/dialog/object-properties.cpp b/src/ui/dialog/object-properties.cpp
index 82b2cf6b1..8f36cba43 100644
--- a/src/ui/dialog/object-properties.cpp
+++ b/src/ui/dialog/object-properties.cpp
@@ -467,6 +467,7 @@ void ObjectProperties::label_changed(void)
blocked = true;
/* Retrieve the label widget for the object's id */
+ //bug 1290573: getId() crashes after undo (cannot create string from NULL ptr)
gchar *id = g_strdup(EntryID.get_text().c_str());
g_strcanon (id, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.:", '_');
if (!strcmp (id, item->getId())) {
diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp
index ebfa16f02..2095546fb 100644
--- a/src/ui/dialog/objects.cpp
+++ b/src/ui/dialog/objects.cpp
@@ -3,6 +3,7 @@
*
* Authors:
* Theodore Janeczko
+ * Tweaked by Liam P White for use in Inkscape
*
* Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
*
@@ -17,20 +18,31 @@
#include <gtkmm/icontheme.h>
#include <gtkmm/imagemenuitem.h>
#include <gtkmm/separatormenuitem.h>
+#include <gtkmm/stock.h>
#include <glibmm/i18n.h>
#include "desktop.h"
#include "desktop-style.h"
+#include "dialogs/dialog-events.h"
#include "document.h"
#include "document-undo.h"
+#include "filter-chemistry.h"
+#include "filters/blend.h"
+#include "filters/gaussian-blur.h"
#include "helper/action.h"
#include "inkscape.h"
+#include "layer-manager.h"
#include "preferences.h"
+#include "selection.h"
+#include "sp-clippath.h"
+#include "sp-mask.h"
#include "sp-item.h"
#include "sp-object.h"
+#include "sp-root.h"
#include "sp-shape.h"
-#include "svg/css-ostringstream.h"
+#include "style.h"
+#include "tools-switch.h"
#include "ui/icon-names.h"
#include "ui/widget/imagetoggler.h"
#include "ui/widget/layertypeicon.h"
@@ -38,29 +50,16 @@
#include "ui/widget/clipmaskicon.h"
#include "ui/widget/highlight-picker.h"
#include "ui/tools/node-tool.h"
+#include "ui/tools/tool-base.h"
#include "verbs.h"
+#include "widgets/sp-color-notebook.h"
#include "widgets/icon.h"
#include "xml/node.h"
#include "xml/node-observer.h"
#include "xml/repr.h"
-#include "sp-root.h"
-//#include "event-context.h"
-#include "selection.h"
-#include "dialogs/dialog-events.h"
-#include "widgets/sp-color-notebook.h"
-#include "style.h"
-#include "filter-chemistry.h"
-#include "filters/blend.h"
-#include "filters/gaussian-blur.h"
-#include "sp-clippath.h"
-#include "sp-mask.h"
-#include "layer-manager.h"
-#include "tools-switch.h"
//#define DUMP_LAYERS 1
-guint get_group0_keyval(GdkEventKey *event);
-
namespace Inkscape {
namespace UI {
namespace Dialog {
@@ -82,7 +81,7 @@ enum {
COL_VISIBLE = 1,
COL_LOCKED,
COL_TYPE,
- COL_INSERTORDER,
+// COL_INSERTORDER,
COL_CLIPMASK,
COL_HIGHLIGHT
};
@@ -106,8 +105,8 @@ enum {
BUTTON_LOCK_ALL,
BUTTON_UNLOCK_ALL,
BUTTON_SETCLIP,
- BUTTON_CLIPGROUP,
- BUTTON_SETINVCLIP,
+// BUTTON_CLIPGROUP,
+// BUTTON_SETINVCLIP,
BUTTON_UNSETCLIP,
BUTTON_SETMASK,
BUTTON_UNSETMASK,
@@ -214,7 +213,7 @@ public:
add(_colType);
add(_colHighlight);
add(_colClipMask);
- add(_colInsertOrder);
+ //add(_colInsertOrder);
}
virtual ~ModelColumns() {}
@@ -225,7 +224,7 @@ public:
Gtk::TreeModelColumn<int> _colType;
Gtk::TreeModelColumn<guint32> _colHighlight;
Gtk::TreeModelColumn<int> _colClipMask;
- Gtk::TreeModelColumn<int> _colInsertOrder;
+ //Gtk::TreeModelColumn<int> _colInsertOrder;
};
/**
@@ -352,13 +351,19 @@ void ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow)
Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend();
Gtk::TreeModel::Row row = *iter;
row[_model->_colObject] = item;
- row[_model->_colLabel] = item->label() ? item->label() : item->getId();
+ //this seems to crash on convert stroke to path then undo (probably no ID?)
+ try {
+ row[_model->_colLabel] = item->label() ? item->label() : item->getId();
+ } catch (...) {
+ row[_model->_colLabel] = Glib::ustring("getId_failure");
+ g_critical("item->getId() failed, using \"getId_failure\"");
+ }
row[_model->_colVisible] = !item->isHidden();
row[_model->_colLocked] = !item->isSensitive();
row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0;
row[_model->_colHighlight] = item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00;
row[_model->_colClipMask] = item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0);
- row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
+ //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
//If our parent object is a group and it's expanded, expand the tree
if (SP_IS_GROUP(obj) && SP_GROUP(obj)->expanded())
@@ -388,7 +393,10 @@ void ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow)
*/
void ObjectsPanel::_updateObject( SPObject *obj, bool recurse ) {
//Find the object in the tree store and update it
+
+ //mark
_store->foreach_iter( sigc::bind<SPObject*>(sigc::mem_fun(*this, &ObjectsPanel::_checkForUpdated), obj) );
+ //end mark
if (recurse)
{
for (SPObject * iter = obj->children; iter != NULL; iter = iter->next)
@@ -419,7 +427,7 @@ bool ObjectsPanel::_checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj)
row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0;
row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0;
row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0;
- row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
+ //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
return true;
}
@@ -685,7 +693,9 @@ void ObjectsPanel::_setLockedIter( const Gtk::TreeModel::iterator& iter, const b
bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event)
{
- switch (get_group0_keyval(event)) {
+ bool empty = _desktop->selection->isEmpty();
+
+ switch (Inkscape::UI::Tools::get_group0_keyval(event)) {
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
case GDK_KEY_F2:
@@ -702,68 +712,33 @@ bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event)
}
break;
case GDK_Home:
- {
//Move item(s) to top of containing group/layer
- if (_desktop->selection->isEmpty())
- {
- _fireAction( SP_VERB_LAYER_TO_TOP );
- }
- else
- {
- _fireAction( SP_VERB_SELECTION_TO_FRONT );
- }
- return true;
- }
+ _fireAction( empty ? SP_VERB_LAYER_TO_TOP : SP_VERB_SELECTION_TO_FRONT );
+ break;
case GDK_End:
- {
//Move item(s) to bottom of containing group/layer
- if (_desktop->selection->isEmpty())
- {
- _fireAction( SP_VERB_LAYER_TO_BOTTOM );
- }
- else
- {
- _fireAction( SP_VERB_SELECTION_TO_BACK );
- }
- return true;
- }
+ _fireAction( empty ? SP_VERB_LAYER_TO_BOTTOM : SP_VERB_SELECTION_TO_BACK );
+ break;
case GDK_KEY_Page_Up:
{
//Move item(s) up in containing group/layer
- if (_desktop->selection->isEmpty())
- {
- _fireAction( SP_VERB_LAYER_RAISE );
- }
- else
- {
- if (event->state & GDK_SHIFT_MASK) {
- _fireAction( SP_VERB_LAYER_MOVE_TO_NEXT );
- } else {
- _fireAction( SP_VERB_SELECTION_RAISE );
- }
- }
- return true;
+ int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_NEXT : SP_VERB_SELECTION_RAISE;
+ _fireAction( empty ? SP_VERB_LAYER_RAISE : ch );
+ break;
}
case GDK_KEY_Page_Down:
{
//Move item(s) down in containing group/layer
- if (_desktop->selection->isEmpty())
- {
- _fireAction( SP_VERB_LAYER_LOWER );
- }
- else
- {
- if (event->state & GDK_SHIFT_MASK) {
- _fireAction( SP_VERB_LAYER_MOVE_TO_PREV );
- } else {
- _fireAction( SP_VERB_SELECTION_LOWER );
- }
- }
- return true;
+ int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_PREV : SP_VERB_SELECTION_LOWER;
+ _fireAction( empty ? SP_VERB_LAYER_LOWER : ch );
+ break;
}
+
//TODO: Handle Ctrl-A, etc.
+ default:
+ return false;
}
- return false;
+ return true;
}
/**
@@ -809,7 +784,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event)
return true;
} else if (col == _tree.get_column(COL_LOCKED-1) ||
col == _tree.get_column(COL_TYPE-1) ||
- col == _tree.get_column(COL_INSERTORDER - 1) ||
+ //col == _tree.get_column(COL_INSERTORDER - 1) ||
col == _tree.get_column(COL_HIGHLIGHT-1)) {
//Click on an icon column, eat this event to keep row selection
return true;
@@ -926,7 +901,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event)
DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS,
newValue? _("Layer to group") : _("Group to layer"));
}
- } else if (col == _tree.get_column(COL_INSERTORDER - 1)) {
+ } /*else if (col == _tree.get_column(COL_INSERTORDER - 1)) {
if (SP_IS_GROUP(item))
{
//Toggle the current item's insert order
@@ -938,7 +913,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event)
DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS,
newValue? _("Set insert mode bottom") : _("Set insert mode top"));
}
- } else if (col == _tree.get_column(COL_HIGHLIGHT - 1)) {
+ }*/ else if (col == _tree.get_column(COL_HIGHLIGHT - 1)) {
//Clear the highlight targets
_highlight_target.clear();
if (_tree.get_selection()->is_selected(path))
@@ -1474,7 +1449,7 @@ void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject * cp)
target->setHighlightColor(rgba);
target->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
}
- DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_OBJECTS, _("Set object highlight color"));
+ DocumentUndo::maybeDone(SP_ACTIVE_DOCUMENT, "highlight", SP_VERB_DIALOG_OBJECTS, _("Set object highlight color"));
}
/**
@@ -1689,13 +1664,13 @@ ObjectsPanel::ObjectsPanel() :
col->add_attribute( typeRenderer->property_active(), _model->_colType );
}
- //Insert order
- Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon());
+ //Insert order (LiamW: unused)
+ /*Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon());
int insertColNum = _tree.append_column("type", *insertRenderer) - 1;
col = _tree.get_column(insertColNum);
if ( col ) {
col->add_attribute( insertRenderer->property_active(), _model->_colInsertOrder );
- }
+ }*/
//Clip/mask
Inkscape::UI::Widget::ClipMaskIcon * clipRenderer = Gtk::manage( new Inkscape::UI::Widget::ClipMaskIcon());
@@ -1807,43 +1782,102 @@ ObjectsPanel::ObjectsPanel() :
SPDesktop* targetDesktop = getDesktop();
//Set up the button row
+
+
+ //Add object/layer
Gtk::Button* btn = Gtk::manage( new Gtk::Button() );
- _styleButton( *btn, GTK_STOCK_ADD, _("New Layer") );
+ btn->set_tooltip_text(_("Add layer..."));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("list-add"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ Gtk::Image *image_add = Gtk::manage(new Gtk::Image());
+ image_add->set_from_icon_name(INKSCAPE_ICON("list-add"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_add);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_NEW) );
_buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK);
+
+ //Remove object
btn = Gtk::manage( new Gtk::Button() );
- _styleButton( *btn, GTK_STOCK_REMOVE, _("Remove") );
+ btn->set_tooltip_text(_("Remove object"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("list-remove"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ Gtk::Image *image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("list-remove"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DELETE) );
_watching.push_back( btn );
_buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK);
+ //Move to bottom
btn = Gtk::manage( new Gtk::Button() );
- _styleButton( *btn, GTK_STOCK_GOTO_BOTTOM, _("Move To Bottom") );
+ btn->set_tooltip_text(_("Move To Bottom"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("go-bottom"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("go-bottom"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_BOTTOM) );
_watchingNonBottom.push_back( btn );
_buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
-
+
+ //Move down
btn = Gtk::manage( new Gtk::Button() );
- _styleButton( *btn, GTK_STOCK_GO_DOWN, _("Move Down") );
+ btn->set_tooltip_text(_("Move Down"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("go-down"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("go-down"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DOWN) );
_watchingNonBottom.push_back( btn );
_buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
+ //Move up
btn = Gtk::manage( new Gtk::Button() );
- _styleButton( *btn, GTK_STOCK_GO_UP, _("Move Up") );
+ btn->set_tooltip_text(_("Move Up"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("go-up"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("go-up"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_UP) );
_watchingNonTop.push_back( btn );
_buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
+ //Move to top
btn = Gtk::manage( new Gtk::Button() );
- _styleButton( *btn, GTK_STOCK_GOTO_TOP, _("Move To Top") );
+ btn->set_tooltip_text(_("Move To Top"));
+#if GTK_CHECK_VERSION(3,10,0)
+ btn->set_image_from_icon_name(INKSCAPE_ICON("go-top"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+#else
+ image_remove = Gtk::manage(new Gtk::Image());
+ image_remove->set_from_icon_name(INKSCAPE_ICON("go-top"), Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ btn->set_image(*image_remove);
+#endif
+ btn->set_relief(Gtk::RELIEF_NONE);
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_TOP) );
_watchingNonTop.push_back( btn );
_buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
- btn = Gtk::manage( new Gtk::Button() );
- _styleButton( *btn, GTK_STOCK_UNINDENT, _("Collapse All") );
+ //Collapse all
+ btn = Gtk::manage( new Gtk::Button(Gtk::Stock::UNINDENT) );
+ btn->set_tooltip_text(_("Collapse All"));
+ btn->set_relief(Gtk::RELIEF_NONE);
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_COLLAPSE_ALL) );
_watchingNonBottom.push_back( btn );
_buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK);
@@ -2042,15 +2076,6 @@ void ObjectsPanel::setDesktop( SPDesktop* desktop )
//should be okay to put these here because they are never referenced anywhere else
using namespace Inkscape::UI::Tools;
-guint get_group0_keyval(GdkEventKey *event) {
- guint keyval = 0;
- gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display(
- gdk_display_get_default()), event->hardware_keycode,
- (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval,
- NULL, NULL, NULL);
- return keyval;
-}
-
void SPItem::setHighlightColor(guint32 const color)
{
g_free(_highlightColor);
@@ -2065,7 +2090,7 @@ void SPItem::setHighlightColor(guint32 const color)
NodeTool *tool = 0;
if (SP_ACTIVE_DESKTOP ) {
- ToolBase *ec = SP_ACTIVE_DESKTOP->event_context;
+ Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context;
if (INK_IS_NODE_TOOL(ec)) {
tool = static_cast<NodeTool*>(ec);
tools_switch(tool->desktop, TOOLS_NODES);
@@ -2079,7 +2104,7 @@ void SPItem::unsetHighlightColor()
_highlightColor = NULL;
NodeTool *tool = 0;
if (SP_ACTIVE_DESKTOP ) {
- ToolBase *ec = SP_ACTIVE_DESKTOP->event_context;
+ Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context;
if (INK_IS_NODE_TOOL(ec)) {
tool = static_cast<NodeTool*>(ec);
tools_switch(tool->desktop, TOOLS_NODES);
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index 2a8471b55..807618b4d 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -6,7 +6,6 @@
* Jon A. Cruz
* John Bintz
* Abhishek Sharma
- * Theodore Janezcko
*
* Copyright (C) 2005 Jon A. Cruz
* Copyright (C) 2008 John Bintz
@@ -21,7 +20,6 @@
#include "swatches.h"
#include <gtkmm/radiomenuitem.h>
-#include <gtkmm/widget.h>
#include <glibmm/i18n.h>
#include <glibmm/main.h>
@@ -47,6 +45,7 @@
#include "sp-gradient.h"
#include "sp-gradient-vector.h"
#include "style.h"
+#include "ui/previewholder.h"
#include "widgets/desktop-widget.h"
#include "widgets/gradient-vector.h"
#include "widgets/eek-preview.h"
@@ -57,2305 +56,1130 @@
#include "verbs.h"
#include "gradient-chemistry.h"
#include "helper/action.h"
-#include "xml/node-observer.h"
-#include "xml/repr.h"
-#include "sp-pattern.h"
-#include "icon-size.h"
-#include "widgets/icon.h"
-#include "filedialog.h"
-#include "sp-stop.h"
-#include "svg/svg-color.h"
-#include "sp-radial-gradient.h"
-#include "color-rgba.h"
-#include "ui/tools/tool-base.h"
-#include "svg/css-ostringstream.h"
-#include <queue>
-#ifdef WIN32
-#include <windows.h>
-#endif
-
-//lazy!
-void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill);
+#include "helper/action-context.h"
namespace Inkscape {
namespace UI {
namespace Dialogs {
-#define SWATCHES_FILE_NAME "swatches.svg"
+#define VBLOCK 16
+#define PREVIEW_PIXBUF_WIDTH 128
-static char* trim( char* str ) {
- char* ret = str;
- while ( *str && (*str == ' ' || *str == '\t') ) {
- str++;
- }
- ret = str;
- while ( *str ) {
- str++;
- }
- str--;
- while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) {
- *str-- = 0;
- }
- return ret;
-}
+void _loadPaletteFile( gchar const *filename, gboolean user=FALSE );
-static void skipWhitespace( char*& str ) {
- while ( *str == ' ' || *str == '\t' ) {
- str++;
+std::list<SwatchPage*> userSwatchPages;
+std::list<SwatchPage*> systemSwatchPages;
+static std::map<SPDocument*, SwatchPage*> docPalettes;
+static std::vector<DocTrack*> docTrackings;
+static std::map<SwatchesPanel*, SPDocument*> docPerPanel;
+
+
+class SwatchesPanelHook : public SwatchesPanel
+{
+public:
+ static void convertGradient( GtkMenuItem *menuitem, gpointer userData );
+ static void deleteGradient( GtkMenuItem *menuitem, gpointer userData );
+};
+
+static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ item->buttonClicked(false);
}
}
-static bool parseNum( char*& str, int& val ) {
- val = 0;
- while ( '0' <= *str && *str <= '9' ) {
- val = val * 10 + (*str - '0');
- str++;
+static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ item->buttonClicked(true);
}
- bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n');
- return retval;
}
-static char * SwatchFile;
-static SPDocument * SwatchDocument;
-static unsigned int page_suffix;
+static GtkWidget* popupMenu = 0;
+static GtkWidget *popupSubHolder = 0;
+static GtkWidget *popupSub = 0;
+static std::vector<Glib::ustring> popupItems;
+static std::vector<GtkWidget*> popupExtras;
+static ColorItem* bounceTarget = 0;
+static SwatchesPanel* bouncePanel = 0;
-static void loadPalletFile()
+static void redirClick( GtkMenuItem *menuitem, gpointer /*user_data*/ )
{
- if (!SwatchDocument) {
- SwatchFile=g_build_filename(INKSCAPE_PALETTESDIR, _("swatches.svg"), NULL);
- SwatchDocument=SPDocument::createNewDoc (SwatchFile, TRUE);
- if (!SwatchDocument) {
- SwatchDocument = SPDocument::createNewDoc(NULL, TRUE, true);
- sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
- }
+ if ( bounceTarget ) {
+ handleClick( GTK_WIDGET(menuitem), bounceTarget );
}
}
-static void addStop( Inkscape::XML::Node *parent, Glib::ustring const &color, gfloat opacity, gchar const *offset )
+static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ )
{
-#ifdef SP_GR_VERBOSE
- g_message("addStop(%p, %s, %d, %s)", parent, color.c_str(), opacity, offset);
-#endif
- Inkscape::XML::Node *stop = parent->document()->createElement("svg:stop");
- {
- gchar *tmp = g_strdup_printf( "stop-color:%s;stop-opacity:%f;", color.c_str(), opacity < 0.0 ? 0.0 : (opacity > 1.0 ? 1.0 : opacity) );
- stop->setAttribute( "style", tmp );
- g_free(tmp);
+ if ( bounceTarget ) {
+ handleSecondaryClick( GTK_WIDGET(menuitem), 0, bounceTarget );
}
-
- stop->setAttribute( "offset", offset );
-
- parent->appendChild(stop);
- Inkscape::GC::release(stop);
}
-static SPGroup* importGPL(SPDocument* doc, const gchar* full)
+static void editGradientImpl( SPDesktop* desktop, SPGradient* gr )
{
- SPGroup* ret = NULL;
- if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) {
-
- /*Load the pallet file here*/
- char block[1024];
- FILE *f = Inkscape::IO::fopen_utf8name( full, "r" );
- if ( f ) {
- char* result = fgets( block, sizeof(block), f );
- if ( result ) {
- if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) {
- bool inHeader = true;
- bool hasErr = false;
-
- Inkscape::XML::Node * page = doc->getReprDoc()->createElement("svg:g");
- gchar *id=NULL;
- do {
- g_free(id);
- id = g_strdup_printf("page%d", page_suffix++);
- } while (doc->getObjectById(id));
-
- page->setAttribute("id", id);
-
- do {
- result = fgets( block, sizeof(block), f );
- block[sizeof(block) - 1] = 0;
- if ( result ) {
- if ( block[0] == '#' ) {
- // ignore comment
- } else {
- char *ptr = block;
- // very simple check for header versus entry
- while ( *ptr == ' ' || *ptr == '\t' ) {
- ptr++;
- }
- if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) {
- // blank line. skip it.
- } else if ( '0' <= *ptr && *ptr <= '9' ) {
- // should be an entry link
- inHeader = false;
- ptr = block;
- Glib::ustring name("");
- skipWhitespace(ptr);
- if ( *ptr ) {
- int r = 0;
- int g = 0;
- int b = 0;
- hasErr = parseNum(ptr, r);
- if ( !hasErr ) {
- skipWhitespace(ptr);
- hasErr = parseNum(ptr, g);
- }
- if ( !hasErr ) {
- skipWhitespace(ptr);
- hasErr = parseNum(ptr, b);
- }
- if ( !hasErr && *ptr ) {
- char* n = trim(ptr);
- if (n != NULL) {
- name = g_dpgettext2(NULL, "Palette", n);
- }
- }
- if ( !hasErr ) {
- // Add the entry now
-
- Inkscape::XML::Node *grad = doc->getReprDoc()->createElement("svg:linearGradient");
- grad->setAttribute("inkscape:label", name.c_str());
- grad->setAttribute( "osb:paint", "solid", 0 );
- SPColor color((float)r / 255, (float)g / 255, (float)b / 255);
- addStop(grad, color.toString(), 1, "0");
- page->appendChild(grad);
- Inkscape::GC::release(grad);
- }
- } else {
- hasErr = true;
- }
- } else {
- if ( !inHeader ) {
- // Hmmm... probably bad. Not quite the format we want?
- hasErr = true;
- } else {
- char* sep = strchr(result, ':');
- if ( sep ) {
- *sep = 0;
- char* val = trim(sep + 1);
- char* name = trim(result);
- if ( *name ) {
- if ( strcmp( "Name", name ) == 0 )
- {
- page->setAttribute("inkscape:label", val);
- }
- } else {
- // error
- hasErr = true;
- }
- } else {
- // error
- hasErr = true;
- }
- }
- }
+ if ( gr ) {
+ bool shown = false;
+ if ( desktop && desktop->doc() ) {
+ Inkscape::Selection *selection = sp_desktop_selection( desktop );
+ GSList const *items = selection->itemList();
+ if (items) {
+ SPStyle *query = sp_style_new( desktop->doc() );
+ int result = objects_query_fillstroke(const_cast<GSList *>(items), query, true);
+ if ( (result == QUERY_STYLE_MULTIPLE_SAME) || (result == QUERY_STYLE_SINGLE) ) {
+ // could be pertinent
+ if (query->fill.isPaintserver()) {
+ SPPaintServer* server = query->getFillPaintServer();
+ if ( SP_IS_GRADIENT(server) ) {
+ SPGradient* grad = SP_GRADIENT(server);
+ if ( grad->isSwatch() && grad->getId() == gr->getId()) {
+ desktop->_dlg_mgr->showDialog("FillAndStroke");
+ shown = true;
}
}
- } while ( result && !hasErr );
- if ( !hasErr ) {
- doc->getDefs()->appendChild(page);
- Inkscape::GC::release(page);
- SPObject* obj = doc->getObjectByRepr(page);
- if (SP_IS_GROUP(obj)) {
- ret = SP_GROUP(obj);
- }
- #if ENABLE_MAGIC_COLORS
- ColorItem::_wireMagicColors( onceMore );
- #endif // ENABLE_MAGIC_COLORS
- } else {
- delete page;
}
}
+ sp_style_unref(query);
}
+ }
- fclose(f);
+ if (!shown) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (prefs->getBool("/dialogs/gradienteditor/showlegacy", false)) {
+ // Legacy gradient dialog
+ GtkWidget *dialog = sp_gradient_vector_editor_new( gr );
+ gtk_widget_show( dialog );
+ } else {
+ // Invoke the gradient tool
+ Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT );
+ if ( verb ) {
+ SPAction *action = verb->get_action( Inkscape::ActionContext( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP ) );
+ if ( action ) {
+ sp_action_perform( action, NULL );
+ }
+ }
+ }
}
- /* end loading the pallet file*/
}
- return ret;
}
-SwatchesPanel& SwatchesPanel::getInstance()
+static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ )
{
- return *new SwatchesPanel();
-}
-
-class SwatchesPanel::StopWatcher : public Inkscape::XML::NodeObserver {
-public:
- StopWatcher(SwatchesPanel* pnl, SPStop* obj) :
- _pnl(pnl),
- _obj(obj),
- _repr(obj->getRepr())
- {
- _repr->addObserver(*this);
- }
-
- ~StopWatcher() {
- _repr->removeObserver(*this);
- }
-
- virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){}
- virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){}
- virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ){}
- virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {}
-
- virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) {
- if (_pnl && _obj) {
- _pnl->_defsChanged( );
- }
- }
-
- SwatchesPanel* _pnl;
- SPStop* _obj;
- Inkscape::XML::Node* _repr;
-};
-
-class SwatchesPanel::GradientWatcher : public Inkscape::XML::NodeObserver {
-public:
- GradientWatcher(SwatchesPanel* pnl, SPGradient* obj) :
- _pnl(pnl),
- _obj(obj),
- _repr(obj->getRepr()),
- _labelAttr(g_quark_from_string("inkscape:label")),
- _swatchAttr(g_quark_from_string("osb:paint"))
- {
- _repr->addObserver(*this);
- }
-
- ~GradientWatcher() {
- _repr->removeObserver(*this);
- }
-
- virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ )
- {
- if ( _pnl && _obj && _obj->isSwatch()) {
- _pnl->_defsChanged( );
- }
- }
- virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ )
- {
- if ( _pnl && _obj && _obj->isSwatch() ) {
- _pnl->_defsChanged( );
- }
- }
- virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ )
- {
- if ( _pnl && _obj && _obj->isSwatch() ) {
- _pnl->_defsChanged( );
- }
- }
- virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {}
- virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) {
- if (_pnl && _obj && ((_obj->isSwatch() && name == _labelAttr) || name == _swatchAttr)) {
- _pnl->_defsChanged( );
- }
- }
-
- SwatchesPanel* _pnl;
- SPGradient* _obj;
- Inkscape::XML::Node* _repr;
- GQuark _labelAttr;
- GQuark _swatchAttr;
-};
-
-class SwatchesPanel::SwatchWatcher : public Inkscape::XML::NodeObserver {
-public:
- SwatchWatcher(SwatchesPanel* pnl, SPObject* obj, bool builtIn) :
- _pnl(pnl),
- _obj(obj),
- _builtIn(builtIn),
- _repr(obj->getRepr()),
- _labelAttr(g_quark_from_string("inkscape:label")),
- _swatchAttr(g_quark_from_string("osb:paint"))
- {
- _repr->addObserver(*this);
- }
-
- ~SwatchWatcher() {
- _repr->removeObserver(*this);
- }
-
- virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ )
- {
- if ( _pnl && _obj) {
- SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0);
- if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) {
- if (_builtIn) {
- _pnl->_swatchesChanged( );
- } else {
- _pnl->_defsChanged( );
+ if ( bounceTarget ) {
+ SwatchesPanel* swp = bouncePanel;
+ SPDesktop* desktop = swp ? swp->getDesktop() : 0;
+ SPDocument *doc = desktop ? desktop->doc() : 0;
+ if (doc) {
+ std::string targetName(bounceTarget->def.descr);
+ const GSList *gradients = doc->getResourceList("gradient");
+ for (const GSList *item = gradients; item; item = item->next) {
+ SPGradient* grad = SP_GRADIENT(item->data);
+ if ( targetName == grad->getId() ) {
+ editGradientImpl( desktop, grad );
+ break;
}
}
}
}
- virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ )
- {
- if ( _pnl && _obj) {
- if (_builtIn) {
- _pnl->_swatchesChanged( );
- } else {
- _pnl->_defsChanged( );
- }
- }
- }
- virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ )
- {
- if ( _pnl && _obj) {
- SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0);
- if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) {
- if (_builtIn) {
- _pnl->_swatchesChanged( );
- } else {
- _pnl->_defsChanged( );
+}
+
+void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData )
+{
+ if ( bounceTarget ) {
+ SwatchesPanel* swp = bouncePanel;
+ SPDesktop* desktop = swp ? swp->getDesktop() : 0;
+ SPDocument *doc = desktop ? desktop->doc() : 0;
+ gint index = GPOINTER_TO_INT(userData);
+ if ( doc && (index >= 0) && (static_cast<guint>(index) < popupItems.size()) ) {
+ Glib::ustring targetName = popupItems[index];
+
+ const GSList *gradients = doc->getResourceList("gradient");
+ for (const GSList *item = gradients; item; item = item->next) {
+ SPGradient* grad = SP_GRADIENT(item->data);
+ if ( targetName == grad->getId() ) {
+ grad->setSwatch();
+ DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT,
+ _("Add gradient stop"));
+ break;
}
}
}
}
- virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {}
- virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) {
- if (_pnl && _obj && name == _labelAttr) {
- if (_builtIn) {
- _pnl->_swatchesChanged( );
- } else {
- _pnl->_defsChanged( );
- }
- }
- }
-
- SwatchesPanel* _pnl;
- SPObject* _obj;
- bool _builtIn;
- Inkscape::XML::Node* _repr;
- GQuark _labelAttr;
- GQuark _swatchAttr;
-};
+}
-class SwatchesPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
+void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*userData*/ )
{
-public:
-
- ModelColumns()
- {
- add(_colObject);
- add(_colLabel);
+ if ( bounceTarget ) {
+ SwatchesPanel* swp = bouncePanel;
+ SPDesktop* desktop = swp ? swp->getDesktop() : 0;
+ sp_gradient_unset_swatch(desktop, bounceTarget->def.descr);
}
- virtual ~ModelColumns() {}
-
- Gtk::TreeModelColumn<SPObject*> _colObject;
- Gtk::TreeModelColumn<Glib::ustring> _colLabel;
-};
+}
-class SwatchesPanel::ModelColumnsDoc : public Gtk::TreeModel::ColumnRecord
+static SwatchesPanel* findContainingPanel( GtkWidget *widget )
{
-public:
+ SwatchesPanel *swp = 0;
- ModelColumnsDoc()
- {
- add(_colObject);
- add(_colLabel);
- add(_colPixbuf);
+ std::map<GtkWidget*, SwatchesPanel*> rawObjects;
+ for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) {
+ rawObjects[GTK_WIDGET(it->first->gobj())] = it->first;
}
- virtual ~ModelColumnsDoc() {}
- Gtk::TreeModelColumn<SPObject*> _colObject;
- Gtk::TreeModelColumn<Glib::ustring> _colLabel;
- Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > _colPixbuf;
-};
-
-static void StripChildGroups(Inkscape::XML::Node * node, SPObject* addTo)
-{
- for (Inkscape::XML::Node * it = node->firstChild(); it != NULL;) {
- if (!strcmp(it->name(), "svg:g")) {
- Inkscape::XML::Node * todel = it;
- it = it->next();
- node->removeChild(todel);
- } else {
- it = it->next();
+ for (GtkWidget* curr = widget; curr && !swp; curr = gtk_widget_get_parent(curr)) {
+ if (rawObjects.find(curr) != rawObjects.end()) {
+ swp = rawObjects[curr];
}
}
- addTo->appendChildRepr(node);
-}
-static void BubbleChildGroups(Inkscape::XML::Node * node, SPObject* addTo)
-{
- std::queue<Inkscape::XML::Node *> groups;
- for (Inkscape::XML::Node * it = node->firstChild(); it != NULL; ) {
- if (!strcmp(it->name(), "svg:g")) {
- groups.push(it->duplicate(addTo->document->getReprDoc()));
- Inkscape::XML::Node * todel = it;
- it = it->next();
- node->removeChild(todel);
- } else {
- it = it->next();
- }
- }
- addTo->appendChildRepr(node);
- while (!groups.empty()) {
- Inkscape::XML::Node * it = groups.front();
- groups.pop();
- BubbleChildGroups(it, addTo);
- Inkscape::GC::release(it);
- }
+ return swp;
}
-void SwatchesPanel::_addSwatchButtonClicked(SPGroup* swatch, bool recurse)
+static void removeit( GtkWidget *widget, gpointer data )
{
- if (_currentDocument) {
- if (swatch && SP_IS_GROUP(swatch) ) {
- Inkscape::XML::Node * copy = swatch->getRepr()->duplicate(_currentDocument->getReprDoc());
- if (recurse) {
- BubbleChildGroups(copy, _currentDocument->getDefs());
- } else {
- StripChildGroups(copy, _currentDocument->getDefs());
- }
- Inkscape::GC::release(copy);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document"));
- }
- }
+ gtk_container_remove( GTK_CONTAINER(data), widget );
}
-void SwatchesPanel::_importButtonClicked(bool addToDoc, bool addToBI)
-{
- if (addToDoc || addToBI) {
- //# Get the current directory for finding files
- static Glib::ustring open_path;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-
- if(open_path.empty())
- {
- Glib::ustring attr = prefs->getString("/dialogs/open/path");
- if (!attr.empty()) open_path = attr;
- }
+/* extern'ed from colot-item.cpp */
+gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data );
- //# Test if the open_path directory exists
- if (!Inkscape::IO::file_test(open_path.c_str(),
- (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
- open_path = "";
-
- #ifdef WIN32
- //# If no open path, default to our win32 documents folder
- if (open_path.empty())
- {
- // The path to the My Documents folder is read from the
- // value "HKEY_CURRENT_USER\Software\Windows\CurrentVersion\Explorer\Shell Folders\Personal"
- HKEY key = NULL;
- if(RegOpenKeyExA(HKEY_CURRENT_USER,
- "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
- 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
+gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data )
+{
+ gboolean handled = FALSE;
+
+ if ( event && (event->button == 3) && (event->type == GDK_BUTTON_PRESS) ) {
+ SwatchesPanel* swp = findContainingPanel( widget );
+
+ if ( !popupMenu ) {
+ popupMenu = gtk_menu_new();
+ GtkWidget* child = 0;
+
+ //TRANSLATORS: An item in context menu on a colour in the swatches
+ child = gtk_menu_item_new_with_label(_("Set fill"));
+ g_signal_connect( G_OBJECT(child),
+ "activate",
+ G_CALLBACK(redirClick),
+ user_data);
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+
+ //TRANSLATORS: An item in context menu on a colour in the swatches
+ child = gtk_menu_item_new_with_label(_("Set stroke"));
+
+ g_signal_connect( G_OBJECT(child),
+ "activate",
+ G_CALLBACK(redirSecondaryClick),
+ user_data);
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+
+ child = gtk_separator_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+ popupExtras.push_back(child);
+
+ child = gtk_menu_item_new_with_label(_("Delete"));
+ g_signal_connect( G_OBJECT(child),
+ "activate",
+ G_CALLBACK(SwatchesPanelHook::deleteGradient),
+ user_data );
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+ popupExtras.push_back(child);
+ gtk_widget_set_sensitive( child, FALSE );
+
+ child = gtk_menu_item_new_with_label(_("Edit..."));
+ g_signal_connect( G_OBJECT(child),
+ "activate",
+ G_CALLBACK(editGradient),
+ user_data );
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+ popupExtras.push_back(child);
+
+ child = gtk_separator_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+ popupExtras.push_back(child);
+
+ child = gtk_menu_item_new_with_label(_("Convert"));
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+ //popupExtras.push_back(child);
+ //gtk_widget_set_sensitive( child, FALSE );
{
- WCHAR utf16path[_MAX_PATH];
- DWORD value_type;
- DWORD data_size = sizeof(utf16path);
- if(RegQueryValueExW(key, L"Personal", NULL, &value_type,
- (BYTE*)utf16path, &data_size) == ERROR_SUCCESS)
- {
- g_assert(value_type == REG_SZ);
- gchar *utf8path = g_utf16_to_utf8(
- (const gunichar2*)utf16path, -1, NULL, NULL, NULL);
- if(utf8path)
- {
- open_path = Glib::ustring(utf8path);
- g_free(utf8path);
- }
- }
+ popupSubHolder = child;
+ popupSub = gtk_menu_new();
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM(child), popupSub );
}
- }
- #endif
- //# If no open path, default to our home directory
- if (open_path.empty())
- {
- open_path = g_get_home_dir();
- open_path.append(G_DIR_SEPARATOR_S);
+ gtk_widget_show_all(popupMenu);
}
- Gtk::Window * parent = SP_ACTIVE_DESKTOP->getToplevel();
- //# Create a dialog
- Inkscape::UI::Dialog::FileOpenDialog *openDialogInstance =
- Inkscape::UI::Dialog::FileOpenDialog::create(
- *parent, open_path,
- Inkscape::UI::Dialog::SWATCH_TYPES,
- _("Select file to open"));
+ if ( user_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
+ bool show = swp && (swp->getSelectedIndex() == 0);
+ for ( std::vector<GtkWidget*>::iterator it = popupExtras.begin(); it != popupExtras.end(); ++ it) {
+ gtk_widget_set_sensitive(*it, show);
+ }
- //# Show the dialog
- bool const success = openDialogInstance->show();
+ bounceTarget = item;
+ bouncePanel = swp;
+ popupItems.clear();
+ if ( popupMenu ) {
+ gtk_container_foreach(GTK_CONTAINER(popupSub), removeit, popupSub);
+ bool processed = false;
+ GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET);
+ if ( wdgt ) {
+ SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt);
+ if ( dtw && dtw->desktop ) {
+ // Pick up all gradients with vectors
+ const GSList *gradients = (dtw->desktop->doc())->getResourceList("gradient");
+ gint index = 0;
+ for (const GSList *curr = gradients; curr; curr = curr->next) {
+ SPGradient* grad = SP_GRADIENT(curr->data);
+ if ( grad->hasStops() && !grad->isSwatch() ) {
+ //gl = g_slist_prepend(gl, curr->data);
+ processed = true;
+ GtkWidget *child = gtk_menu_item_new_with_label(grad->getId());
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupSub), child);
+
+ popupItems.push_back(grad->getId());
+ g_signal_connect( G_OBJECT(child),
+ "activate",
+ G_CALLBACK(SwatchesPanelHook::convertGradient),
+ GINT_TO_POINTER(index) );
+ index++;
+ }
+ }
- //# Save the folder the user selected for later
- open_path = openDialogInstance->getCurrentDirectory();
+ gtk_widget_show_all(popupSub);
+ }
+ }
+ gtk_widget_set_sensitive( popupSubHolder, processed );
- if (!success)
- {
- delete openDialogInstance;
- return;
+ gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time);
+ handled = TRUE;
+ }
}
+ }
- //# User selected something. Get name and type
- Glib::ustring fileName = openDialogInstance->getFilename();
-
- //# We no longer need the file dialog object - delete it
- delete openDialogInstance;
- openDialogInstance = NULL;
+ return handled;
+}
- if (!fileName.empty())
- {
- Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
-
- if ( newFileName.size() > 0)
- fileName = newFileName;
- else
- g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
-
- open_path = Glib::path_get_dirname (fileName);
- open_path.append(G_DIR_SEPARATOR_S);
- prefs->setString("/dialogs/open/path", open_path);
-
- SPDocument* importdoc = SPDocument::createNewDoc(fileName.c_str(), true);
- Inkscape::XML::Node * page = NULL;
- if (importdoc && importdoc->getDefs()) {
- if (addToBI) {
- page = SwatchDocument->getReprDoc()->createElement("svg:g");
- gchar *id=NULL;
- do {
- g_free(id);
- id = g_strdup_printf("page%d", page_suffix++);
- } while (SwatchDocument->getObjectById(id));
-
- page->setAttribute("id", id);
- gchar* name = g_path_get_basename(importdoc->getName());
- page->setAttribute("inkscape:label", name);
- g_free(name);
- }
+static char* trim( char* str ) {
+ char* ret = str;
+ while ( *str && (*str == ' ' || *str == '\t') ) {
+ str++;
+ }
+ ret = str;
+ while ( *str ) {
+ str++;
+ }
+ str--;
+ while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) {
+ *str-- = 0;
+ }
+ return ret;
+}
- for (SPObject* it = importdoc->getDefs()->firstChild(); it != NULL; it = it->next) {
- if (SP_IS_GROUP(it)) {
- if (page) {
- Inkscape::XML::Node * copy = it->getRepr()->duplicate(SwatchDocument->getReprDoc());
- page->appendChild(copy);
- }
- if (addToDoc) {
- _addSwatchButtonClicked(SP_GROUP(it), false);
- }
- }
- }
- if (page) {
- SwatchDocument->getDefs()->appendChildRepr(page);
- sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
- }
+static void skipWhitespace( char*& str ) {
+ while ( *str == ' ' || *str == '\t' ) {
+ str++;
+ }
+}
- importdoc->doUnref();
- } else {
- SPGroup* g = importGPL(addToBI ? SwatchDocument : _currentDocument, fileName.c_str());
- if (addToBI) {
- if (addToDoc) {
- _addSwatchButtonClicked(g, false);
- }
- sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
- } else {
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document"));
- }
- }
- }
+static bool parseNum( char*& str, int& val ) {
+ val = 0;
+ while ( '0' <= *str && *str <= '9' ) {
+ val = val * 10 + (*str - '0');
+ str++;
}
+ bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n');
+ return retval;
}
-void SwatchesPanel::SetSelectedFill(SPGradient* swatch)
+
+void _loadPaletteFile( gchar const *filename, gboolean user/*=FALSE*/ )
{
- if (_currentDesktop && _currentDocument) {
- SPItem* it = _currentDesktop->selection->singleItem();
- if (it) {
- if (it->style->fill.isSet()) {
- if (it->style->fill.isPaintserver()) {
- SPPaintServer * server = it->style->getFillPaintServer();
- if (SP_IS_GRADIENT(server)) {
- SPGradient *grad = SP_GRADIENT(server)->getVector();
- Inkscape::XML::Node * repr = grad->getRepr();
- Inkscape::XML::Node * drepr = swatch->getRepr();
- if (repr != drepr && grad != swatch) {
- while (SPStop* olds = swatch->getFirstStop()) {
- olds->deleteObject();
- }
- for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) {
- Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc());
- swatch->appendChildRepr(clone);
- Inkscape::GC::release(clone);
+ char block[1024];
+ FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" );
+ if ( f ) {
+ char* result = fgets( block, sizeof(block), f );
+ if ( result ) {
+ if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) {
+ bool inHeader = true;
+ bool hasErr = false;
+
+ SwatchPage *onceMore = new SwatchPage();
+
+ do {
+ result = fgets( block, sizeof(block), f );
+ block[sizeof(block) - 1] = 0;
+ if ( result ) {
+ if ( block[0] == '#' ) {
+ // ignore comment
+ } else {
+ char *ptr = block;
+ // very simple check for header versus entry
+ while ( *ptr == ' ' || *ptr == '\t' ) {
+ ptr++;
}
- swatch->setSwatch();
- if (!_noLink.get_active()) {
- sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL);
+ if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) {
+ // blank line. skip it.
+ } else if ( '0' <= *ptr && *ptr <= '9' ) {
+ // should be an entry link
+ inHeader = false;
+ ptr = block;
+ Glib::ustring name("");
+ skipWhitespace(ptr);
+ if ( *ptr ) {
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ hasErr = parseNum(ptr, r);
+ if ( !hasErr ) {
+ skipWhitespace(ptr);
+ hasErr = parseNum(ptr, g);
+ }
+ if ( !hasErr ) {
+ skipWhitespace(ptr);
+ hasErr = parseNum(ptr, b);
+ }
+ if ( !hasErr && *ptr ) {
+ char* n = trim(ptr);
+ if (n != NULL) {
+ name = g_dpgettext2(NULL, "Palette", n);
+ }
+ }
+ if ( !hasErr ) {
+ // Add the entry now
+ Glib::ustring nameStr(name);
+ ColorItem* item = new ColorItem( r, g, b, nameStr );
+ onceMore->_colors.push_back(item);
+ }
+ } else {
+ hasErr = true;
+ }
+ } else {
+ if ( !inHeader ) {
+ // Hmmm... probably bad. Not quite the format we want?
+ hasErr = true;
+ } else {
+ char* sep = strchr(result, ':');
+ if ( sep ) {
+ *sep = 0;
+ char* val = trim(sep + 1);
+ char* name = trim(result);
+ if ( *name ) {
+ if ( strcmp( "Name", name ) == 0 )
+ {
+ onceMore->_name = val;
+ }
+ else if ( strcmp( "Columns", name ) == 0 )
+ {
+ gchar* endPtr = 0;
+ guint64 numVal = g_ascii_strtoull( val, &endPtr, 10 );
+ if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) {
+ // overflow
+ } else if ( (numVal == 0) && (endPtr == val) ) {
+ // failed conversion
+ } else {
+ onceMore->_prefWidth = numVal;
+ }
+ }
+ } else {
+ // error
+ hasErr = true;
+ }
+ } else {
+ // error
+ hasErr = true;
+ }
+ }
}
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch"));
}
}
- } else if (it->style->fill.isColor()) {
- while (SPStop* olds = swatch->getFirstStop()) {
- olds->deleteObject();
- }
- addStop(swatch->getRepr(), it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0");
- swatch->setSwatch();
- if (!_noLink.get_active()) {
- SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch);
- sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL);
- }
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch"));
+ } while ( result && !hasErr );
+ if ( !hasErr ) {
+ if (user)
+ userSwatchPages.push_back(onceMore);
+ else
+ systemSwatchPages.push_back(onceMore);
+#if ENABLE_MAGIC_COLORS
+ ColorItem::_wireMagicColors( onceMore );
+#endif // ENABLE_MAGIC_COLORS
+ } else {
+ delete onceMore;
}
}
}
+
+ fclose(f);
}
}
-void SwatchesPanel::SetSelectedStroke(SPGradient* swatch)
+static bool
+compare_swatch_names(SwatchPage const *a, SwatchPage const *b) {
+
+ return g_utf8_collate(a->_name.c_str(), b->_name.c_str()) < 0;
+}
+
+static void loadEmUp()
{
- if (_currentDesktop && _currentDocument) {
- SPItem* it = _currentDesktop->selection->singleItem();
- if (it) {
- if (it->style->stroke.isSet()) {
- if (it->style->stroke.isPaintserver()) {
- SPPaintServer * server = it->style->getStrokePaintServer();
- if (SP_IS_GRADIENT(server)) {
- SPGradient *grad = SP_GRADIENT(server)->getVector();
- Inkscape::XML::Node * repr = grad->getRepr();
- Inkscape::XML::Node * drepr = swatch->getRepr();
- if (repr != drepr && grad != swatch) {
- while (SPStop* olds = swatch->getFirstStop()) {
- olds->deleteObject();
- }
- for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) {
- Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc());
- swatch->appendChildRepr(clone);
- Inkscape::GC::release(clone);
- }
- swatch->setSwatch();
- if (!_noLink.get_active()) {
- sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE);
+ static bool beenHere = false;
+ gboolean userPalete = true;
+ if ( !beenHere ) {
+ beenHere = true;
+
+ std::list<gchar *> sources;
+ sources.push_back( profile_path("palettes") );
+ sources.push_back( g_strdup(INKSCAPE_PALETTESDIR) );
+ sources.push_back( g_strdup(CREATE_PALETTESDIR) );
+
+ // Use this loop to iterate through a list of possible document locations.
+ while (!sources.empty()) {
+ gchar *dirname = sources.front();
+ if ( Inkscape::IO::file_test( dirname, G_FILE_TEST_EXISTS )
+ && Inkscape::IO::file_test( dirname, G_FILE_TEST_IS_DIR )) {
+ GError *err = 0;
+ GDir *directory = g_dir_open(dirname, 0, &err);
+ if (!directory) {
+ gchar *safeDir = Inkscape::IO::sanitizeString(dirname);
+ g_warning(_("Palettes directory (%s) is unavailable."), safeDir);
+ g_free(safeDir);
+ } else {
+ gchar *filename = 0;
+ while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) {
+ gchar* lower = g_ascii_strdown( filename, -1 );
+// if ( g_str_has_suffix(lower, ".gpl") ) {
+ if ( !g_str_has_suffix(lower, "~") ) {
+ gchar* full = g_build_filename(dirname, filename, NULL);
+ if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) {
+ _loadPaletteFile(full, userPalete);
}
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch"));
- }
- }
- } else if (it->style->stroke.isColor()) {
- while (SPStop* olds = swatch->getFirstStop()) {
- olds->deleteObject();
+ g_free(full);
+ }
+// }
+ g_free(lower);
}
- addStop(swatch->getRepr(), it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0");
- swatch->setSwatch();
- if (!_noLink.get_active()) {
- SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch);
- sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE);
- }
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch"));
+ g_dir_close(directory);
}
}
- }
- }
-}
-void SwatchesPanel::MoveSwatchDown(SPGradient* swatch)
-{
- if (_currentDocument && swatch) {
- SPObject* next = swatch->next;
- while (next && (!SP_IS_GRADIENT(next) || !(SP_GRADIENT(next)->isSwatch()))) {
- next = next->next;
- }
- if (next) {
- Inkscape::XML::Node* repr = swatch->getRepr();
- repr->parent()->changeOrder(repr, next->getRepr());
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Right"));
+ // toss the dirname
+ g_free(dirname);
+ sources.pop_front();
+ userPalete = false;
}
}
-}
-void SwatchesPanel::MoveSwatchUp(SPGradient* swatch)
-{
- if (_currentDocument && swatch) {
- SPObject* g = NULL;
- SPObject* next = swatch->parent->firstChild();
- while (next && next != swatch) {
- if (SP_IS_GRADIENT(next) && SP_GRADIENT(next)->isSwatch()) {
- g = next;
- }
- next = next->next;
- }
- if (g) {
- g = g->getPrev();
- Inkscape::XML::Node* repr = swatch->getRepr();
- repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Left"));
- }
- }
+ // Sort the list of swatches by name, grouped by user/system
+ userSwatchPages.sort(compare_swatch_names);
+ systemSwatchPages.sort(compare_swatch_names);
+
}
-void SwatchesPanel::RemoveSwatch(SPGradient* swatch)
+
+
+SwatchesPanel& SwatchesPanel::getInstance()
{
- if (_currentDocument) {
- if (swatch->isReferenced()) {
- Inkscape::XML::Node * repr = swatch->getRepr();
- repr->parent()->removeChild(repr);
- _currentDocument->getDefs()->getRepr()->appendChild(repr);
- SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false);
- } else {
- swatch->deleteObject(false);
- }
- }
+ return *new SwatchesPanel();
}
-void SwatchesPanel::_setSelectionSwatch(SPGradient* swatch, bool isStroke)
+
+/**
+ * Constructor
+ */
+SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
+ Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, "", true),
+ _holder(0),
+ _clear(0),
+ _remove(0),
+ _currentIndex(0),
+ _currentDesktop(0),
+ _currentDocument(0)
{
- if (_currentDocument) {
- if (swatch) {
- if (_noLink.get_active()) {
- if (swatch->isSolid()) {
- ColorRGBA rgba(swatch->getFirstStop()->getEffectiveColor().toRGBA32(swatch->getFirstStop()->opacity));
- sp_desktop_set_color(_currentDesktop, rgba, false, !isStroke);
+ Gtk::RadioMenuItem* hotItem = 0;
+ _holder = new PreviewHolder();
+ _clear = new ColorItem( ege::PaintDef::CLEAR );
+ _remove = new ColorItem( ege::PaintDef::NONE );
+ if (docPalettes.empty()) {
+ SwatchPage *docPalette = new SwatchPage();
+
+ docPalette->_name = "Auto";
+ docPalettes[0] = docPalette;
+ }
+
+ loadEmUp();
+ if ( !systemSwatchPages.empty() ) {
+ SwatchPage* first = 0;
+ int index = 0;
+ Glib::ustring targetName;
+ if ( !_prefs_path.empty() ) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ targetName = prefs->getString(_prefs_path + "/palette");
+ if (!targetName.empty()) {
+ if (targetName == "Auto") {
+ first = docPalettes[0];
} else {
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0");
-
- Inkscape::XML::Node * clone = swatch->getRepr()->duplicate(_currentDocument->getReprDoc());
- _currentDocument->getDefs()->appendChildRepr(clone);
- SPGradient* grad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone));
- Inkscape::GC::release(clone);
- grad->setSwatch(false);
- SPGradient* normalized = sp_gradient_ensure_vector_normalized(grad);
-// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) {
-// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true);
-// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL);
-// }
- sp_desktop_set_style(_currentDesktop, css);
- sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke);
- sp_repr_css_attr_unref (css);
+ //index++;
+ std::vector<SwatchPage*> pages = _getSwatchSets();
+ for ( std::vector<SwatchPage*>::iterator iter = pages.begin(); iter != pages.end(); ++iter ) {
+ if ( (*iter)->_name == targetName ) {
+ first = *iter;
+ break;
+ }
+ index++;
+ }
}
- } else {
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0");
-
- SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch);
-// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) {
-// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true);
-// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL);
-// }
- sp_desktop_set_style(_currentDesktop, css);
- sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke);
- sp_repr_css_attr_unref (css);
}
- } else {
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property (css, isStroke ? "stroke" : "fill", "none");
- sp_desktop_set_style(_currentDesktop, css);
}
- if (isStroke) {
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item stroke swatch"));
+
+ if ( !first ) {
+ first = docPalettes[0];
+ _currentIndex = 0;
} else {
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item fill swatch"));
+ _currentIndex = index;
}
- }
-}
-void SwatchesPanel::_swatchClicked(GdkEventButton* event, SPGradient* swatch)
-{
- if (_currentDesktop) {
- if (event->button == 3) {
- Gtk::Menu * menu = Gtk::manage(new Gtk::Menu());
-
- Gtk::MenuItem* mi;
-
- Glib::ustring us = Glib::ustring::compose("<b>%1</b>", swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]"));
- mi = Gtk::manage(new Gtk::MenuItem(swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]")));
- Gtk::Label* namelbl = dynamic_cast<Gtk::Label*>(mi->get_child());
- if (namelbl) {
- namelbl->set_markup(us);
- }
- mi->show();
- mi->set_sensitive(false);
- menu->append(*mi);
-
- Gtk::SeparatorMenuItem* sep;
- sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- menu->append(*sep);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Set Fill")));
- mi->signal_activate().connect_notify(sigc::bind<SPGradient*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, false));
- mi->show();
- mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty());
- menu->append(*mi);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Set Stroke")));
- mi->signal_activate().connect_notify(sigc::bind<SPGradient*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, true));
- mi->show();
- mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty());
- menu->append(*mi);
-
- if (swatch) {
- sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- menu->append(*sep);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Fill")));
- mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedFill), swatch));
- mi->show();
- mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem());
- menu->append(*mi);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Stroke")));
- mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedStroke), swatch));
- mi->show();
- mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem());
- menu->append(*mi);
-
-
- sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- menu->append(*sep);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Move Left")));
- mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchUp), swatch));
- mi->show();
- menu->append(*mi);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Move Right")));
- mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchDown), swatch));
- mi->show();
- menu->append(*mi);
-
- sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- menu->append(*sep);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Remove")));
- mi->signal_activate().connect_notify(sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SwatchesPanel::RemoveSwatch), swatch));
- mi->show();
- menu->append(*mi);
+ _rebuild();
+
+ Gtk::RadioMenuItem::Group groupOne;
+
+ int i = 0;
+ std::vector<SwatchPage*> swatchSets = _getSwatchSets();
+ for ( std::vector<SwatchPage*>::iterator it = swatchSets.begin(); it != swatchSets.end(); ++it) {
+ SwatchPage* curr = *it;
+ Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, curr->_name));
+ if ( curr == first ) {
+ hotItem = single;
}
+ _regItem( single, 3, i );
- menu->popup(event->button, event->time);
- } else if (!_currentDesktop->selection->isEmpty()) {
- _setSelectionSwatch(swatch, event->state & GDK_SHIFT_MASK);
+ i++;
}
}
-}
-void SwatchesPanel::MoveDown(SPGroup* page)
-{
- if (_currentDocument && page) {
- SPObject* next = page->next;
- while (next && !SP_IS_GROUP(next)) {
- next = next->next;
- }
- if (next) {
- Inkscape::XML::Node* repr = page->getRepr();
- repr->parent()->changeOrder(repr, next->getRepr());
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Down"));
+ if (Glib::ustring(prefsPath) == "/dialogs/swatches") {
+ Gtk::Requisition sreq;
+#if WITH_GTKMM_3_0
+ Gtk::Requisition sreq_natural;
+ get_preferred_size(sreq_natural, sreq);
+#else
+ sreq = size_request();
+#endif
+ int minHeight = 60;
+ if (sreq.height < minHeight) {
+ set_size_request(70, minHeight);
}
}
-}
-void SwatchesPanel::MoveUp(SPGroup* page)
-{
- if (_currentDocument && page) {
- SPObject* g = NULL;
- SPObject* next = page->parent->firstChild();
- while (next && next != page) {
- if (SP_IS_GROUP(next)) {
- g = next;
- }
- next = next->next;
- }
- if (g) {
- g = g->getPrev();
- Inkscape::XML::Node* repr = page->getRepr();
- repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Up"));
- }
- }
-}
+ _getContents()->pack_start(*_holder, Gtk::PACK_EXPAND_WIDGET);
+ _setTargetFillable(_holder);
-void SwatchesPanel::Remove(SPGroup* page)
-{
- if (_currentDocument && page) {
- std::vector<Inkscape::XML::Node*> toMove;
- for(SPObject* obj = page->firstChild(); obj != NULL; obj = obj->next) {
- if (SP_IS_GRADIENT(obj)) {
- SPGradient* grad = SP_GRADIENT(obj);
- if (grad->isReferenced()) {
- toMove.push_back(grad->getRepr());
- }
- }
- }
- while (!toMove.empty()) {
- Inkscape::XML::Node * repr = toMove.back();
- toMove.pop_back();
- repr->parent()->removeChild(repr);
- _currentDocument->getDefs()->getRepr()->appendChild(repr);
- SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false);
- }
- page->deleteObject(false);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Remove Swatch Group"));
- }
-}
+ show_all_children();
-void SwatchesPanel::AddSelectedFill(SPGroup* page)
-{
- if (_currentDesktop && _currentDocument) {
- SPItem* it = _currentDesktop->selection->singleItem();
- if (it) {
- if (it->style->fill.isSet()) {
- if (it->style->fill.isPaintserver()) {
- SPPaintServer * server = it->style->getFillPaintServer();
- if (SP_IS_GRADIENT(server)) {
- SPGradient *grad = SP_GRADIENT(server)->getVector();
- if (_noLink.get_active()) {
- Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc());
- clone->setAttribute( "osb:paint", "gradient", 0 );
- if (page) {
- page->appendChildRepr(clone);
- } else {
- _currentDocument->getDefs()->appendChildRepr(clone);
- }
- Inkscape::GC::release(clone);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
- } else if (grad->isSwatch()) {
- Inkscape::XML::Node * repr = grad->getRepr();
- Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc());
- if (page) {
- page->appendChildRepr(clone);
- } else {
- _currentDocument->getDefs()->appendChildRepr(clone);
- }
- SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone));
-
- sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL);
- Inkscape::GC::release(clone);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
- } else {
- Inkscape::XML::Node * repr = grad->getRepr();
- Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr();
- if (repr->parent() != drepr) {
- repr->parent()->removeChild(repr);
- drepr->appendChild(repr);
- }
- SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch();
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
- }
- }
- } else if (it->style->fill.isColor()) {
- Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient");
- grad->setAttribute( "osb:paint", "solid", 0 );
- addStop(grad, it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0");
- if (page) {
- page->appendChild(grad);
- } else {
- _currentDocument->getDefs()->appendChild(grad);
- }
- SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad)));
- Inkscape::GC::release(grad);
- if (!_noLink.get_active()) {
- sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL);
- }
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch"));
- }
- }
- }
+ restorePanelPrefs();
+ if ( hotItem ) {
+ hotItem->set_active();
}
}
-void SwatchesPanel::AddSelectedStroke(SPGroup* page)
+SwatchesPanel::~SwatchesPanel()
{
- if (_currentDesktop && _currentDocument) {
- SPItem* it = _currentDesktop->selection->singleItem();
- if (it) {
- if (it->style->stroke.isSet()) {
- if (it->style->stroke.isPaintserver()) {
- SPPaintServer * server = it->style->getStrokePaintServer();
- if (SP_IS_GRADIENT(server)) {
- SPGradient *grad = SP_GRADIENT(server)->getVector();
- if (_noLink.get_active()) {
- Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc());
- clone->setAttribute( "osb:paint", "gradient", 0 );
- if (page) {
- page->appendChildRepr(clone);
- } else {
- _currentDocument->getDefs()->appendChildRepr(clone);
- }
- Inkscape::GC::release(clone);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
- } else if (grad->isSwatch()) {
- Inkscape::XML::Node * repr = grad->getRepr();
- Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc());
- if (page) {
- page->appendChildRepr(clone);
- } else {
- _currentDocument->getDefs()->appendChildRepr(clone);
- }
- SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone));
-
- sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE);
- Inkscape::GC::release(clone);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
- } else {
- Inkscape::XML::Node * repr = grad->getRepr();
- Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr();
- if (repr->parent() != drepr) {
- repr->parent()->removeChild(repr);
- drepr->appendChild(repr);
- }
- SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch();
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch"));
- }
- }
- } else if (it->style->stroke.isColor()) {
- Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient");
- grad->setAttribute( "osb:paint", "solid", 0 );
- addStop(grad, it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0");
- if (page) {
- page->appendChild(grad);
- } else {
- _currentDocument->getDefs()->appendChild(grad);
- }
- SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad)));
- Inkscape::GC::release(grad);
- if (!_noLink.get_active()) {
- sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE);
- }
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch"));
- }
- }
- }
- }
-}
+ _trackDocument( this, 0 );
-void SwatchesPanel::_addBIButtonClicked(GdkEventButton* event)
-{
- if (popUpImportMenu) {
- popUpImportMenu->popup(event->button, event->time);
- }
-}
+ _documentConnection.disconnect();
+ _selChanged.disconnect();
-void SwatchesPanel::NewGroupBI()
-{
- if (_currentDocument) {
- Inkscape::XML::Node * page = SwatchDocument->getReprDoc()->createElement("svg:g");
- gchar *id=NULL;
- do {
- g_free(id);
- id = g_strdup_printf("page%d", page_suffix++);
- } while (SwatchDocument->getObjectById(id));
-
- page->setAttribute("id", id);
-
- SwatchDocument->getDefs()->appendChild(page);
- sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
+ if ( _clear ) {
+ delete _clear;
}
-}
-
-void SwatchesPanel::NewGroup()
-{
- if (_currentDocument) {
- Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g");
- gchar *id=NULL;
- do {
- g_free(id);
- id = g_strdup_printf("page%d", page_suffix++);
- } while (_currentDocument->getObjectById(id));
-
- page->setAttribute("id", id);
-
- _currentDocument->getDefs()->appendChild(page);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("New Swatch Group"));
+ if ( _remove ) {
+ delete _remove;
}
-}
-
-void SwatchesPanel::SaveAs()
-{
- if (_currentDocument) {
- Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g");
- gchar *id=NULL;
- do {
- g_free(id);
- id = g_strdup_printf("page%d", page_suffix++);
- } while (_currentDocument->getObjectById(id));
-
- page->setAttribute("id", id);
-
- std::vector<Inkscape::XML::Node*> toMove;
- for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) {
- if (SP_IS_GRADIENT(it)) {
- SPGradient* grad = SP_GRADIENT(it);
- if (grad->isSwatch()) {
- toMove.push_back(grad->getRepr());
- }
- }
- }
- while (!toMove.empty()) {
- Inkscape::XML::Node* repr = toMove.back();
- toMove.pop_back();
- repr->parent()->removeChild(repr);
- page->appendChild(repr);
- }
- _currentDocument->getDefs()->appendChild(page);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Save Swatch Group"));
+ if ( _holder ) {
+ delete _holder;
}
}
-void SwatchesPanel::Duplicate(SPGroup* oldpage)
+void SwatchesPanel::setOrientation(SPAnchorType how)
{
- if (_currentDocument) {
- Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g");
- gchar *id=NULL;
- do {
- g_free(id);
- id = g_strdup_printf("page%d", page_suffix++);
- } while (_currentDocument->getObjectById(id));
-
- page->setAttribute("id", id);
- if (oldpage->label()) page->setAttribute("inkscape:label", oldpage->label());
-
- for (SPObject *it = oldpage->firstChild(); it != NULL; it = it->next) {
- if (SP_IS_GRADIENT(it)) {
- SPGradient* grad = SP_GRADIENT(it);
- if (grad->isSwatch()) {
- Inkscape::XML::Node * copy = grad->getRepr()->duplicate(_currentDocument->getReprDoc());
- page->appendChild(copy);
- Inkscape::GC::release(copy);
- }
- }
- }
- _currentDocument->getDefs()->appendChild(page);
- DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Duplicate Swatch Group"));
- }
-}
+ // Must call the parent class or bad things might happen
+ Inkscape::UI::Widget::Panel::setOrientation( how );
-void SwatchesPanel::_lblClick(GdkEventButton* event, SPGroup* page)
-{
- Gtk::Menu * menu = Gtk::manage(new Gtk::Menu());
-
- Gtk::MenuItem* mi;
- Glib::ustring us = Glib::ustring::compose("<b>%1</b>", page ? (page->label() ? page->label() : page->getId()) : _("[Base]"));
- mi = Gtk::manage(new Gtk::MenuItem(page ? (page->label() ? page->label() : page->getId()) : _("[Base]")));
- Gtk::Label* namelbl = dynamic_cast<Gtk::Label*>(mi->get_child());
- if (namelbl) {
- namelbl->set_markup(us);
- }
- mi->show();
- mi->set_sensitive(false);
- menu->append(*mi);
-
- Gtk::SeparatorMenuItem* sep;
- sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- menu->append(*sep);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Fill")));
- mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedFill), page));
- mi->show();
- mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem());
- menu->append(*mi);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Stroke")));
- mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedStroke), page));
- mi->show();
- mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem());
- menu->append(*mi);
-
- sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- menu->append(*sep);
-
- if (page) {
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Move Up")));
- mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::MoveUp), page));
- mi->show();
- menu->append(*mi);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Move Down")));
- mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::MoveDown), page));
- mi->show();
- menu->append(*mi);
-
- sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- menu->append(*sep);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Duplicate")));
- mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::Duplicate), page));
- mi->show();
- menu->append(*mi);
-
- sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- menu->append(*sep);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Remove")));
- mi->signal_activate().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::Remove), page));
- mi->show();
- menu->append(*mi);
- } else {
- mi = Gtk::manage(new Gtk::MenuItem(_("Create New Group")));
- mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroup));
- mi->show();
- menu->append(*mi);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Save As New Group")));
- mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::SaveAs));
- mi->show();
- menu->append(*mi);
+ if ( _holder )
+ {
+ _holder->setOrientation(SP_ANCHOR_SOUTH);
}
-
- menu->popup(event->button, event->time);
}
-void SwatchesPanel::_defsChanged()
+void SwatchesPanel::setDesktop( SPDesktop* desktop )
{
- if (_storeDoc) {
- _storeDoc->clear();
- }
-
- while (!docWatchers.empty()) {
- Inkscape::XML::NodeObserver* w = docWatchers.back();
- docWatchers.pop_back();
- delete w;
- }
-
- std::vector<Gtk::Widget *> tableChildren = _insideTable.get_children();
- for (std::vector<Gtk::Widget *>::iterator c = tableChildren.begin(); c != tableChildren.end(); ++c) {
- _insideTable.remove(**c);
- }
-
- if (_currentDocument) {
- Gtk::EventBox* eb;
- Gtk::Label* lbl;
- if (_showlabels) {
- eb = Gtk::manage(new Gtk::EventBox());
- eb->add_events(Gdk::BUTTON_PRESS_MASK);
- eb->signal_button_press_event().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), NULL));
-
- lbl = Gtk::manage(new Gtk::Label(_("[Base]")));
- eb->add(*lbl);
- _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0);
+ if ( desktop != _currentDesktop ) {
+ if ( _currentDesktop ) {
+ _documentConnection.disconnect();
+ _selChanged.disconnect();
}
- ColorItem* item = Gtk::manage(new ColorItem(NULL, _("[None]"), _currentDesktop));
- item->signal_button_press_event().connect_notify(sigc::bind<SPGradient *>(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL));
- item->set_tooltip_text(_("[None]"));
- _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ );
-
- unsigned int i = 1;
- for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) {
- if (SP_IS_GRADIENT(it)) {
- SPGradient* grad = SP_GRADIENT(it);
- if (grad->hasStops()) {
-
- GradientWatcher* w = new GradientWatcher(this, grad);
- docWatchers.push_back(w);
-
- if (grad->isSwatch()) {
-
- for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) {
- StopWatcher* sw = new StopWatcher(this, s);
- docWatchers.push_back(sw);
- }
-
- if (_storeDoc) {
- Gtk::TreeModel::iterator iter = _storeDoc->append();
- Gtk::TreeModel::Row row = *iter;
- row[_modelDoc->_colObject] = grad;
- row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId();
- GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18);
- row[_modelDoc->_colPixbuf] = Glib::wrap(pixb);
- }
+ _currentDesktop = desktop;
- item = Gtk::manage(new ColorItem(grad, it->label() ? it->label() : it->getId(), _currentDesktop));
- item->signal_button_press_event().connect_notify(sigc::bind<SPGradient *>(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad));
- item->set_tooltip_text(it->label() ? it->label() : it->getId());
- if (_showlabels) {
- _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ );
- } else {
- _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ );
- }
+ if ( desktop ) {
+ _currentDesktop->selection->connectChanged(
+ sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
- i++;
- }
- }
- }
- }
-
- for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) {
- if (SP_IS_GROUP(it)) {
- SwatchWatcher* w = new SwatchWatcher(this, it, false);
- docWatchers.push_back(w);
-
- if (_showlabels) {
- i += 20 - (i % 20);
- eb = Gtk::manage(new Gtk::EventBox());
- eb->add_events(Gdk::BUTTON_PRESS_MASK);
- eb->signal_button_press_event().connect_notify(sigc::bind<SPGroup*>(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), SP_GROUP(it)));
- lbl = Gtk::manage(new Gtk::Label(it->label() ? it->label() : it->getId()));
- eb->add(*lbl);
- _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0);
- }
-
- Gtk::TreeModel::iterator rowiter;
-
- if (_storeDoc) {
- rowiter = _storeDoc->append();
- Gtk::TreeModel::Row row = *rowiter;
- row[_modelDoc->_colObject] = it;
- row[_modelDoc->_colLabel] = it->label() ? it->label() : it->getId();
- }
-
- for (SPObject *cit = it->firstChild(); cit != NULL; cit = cit->next) {
- if (SP_IS_GRADIENT(cit)) {
- SPGradient* grad = SP_GRADIENT(cit);
-
- if (grad->hasStops()) {
-
- GradientWatcher* w = new GradientWatcher(this, grad);
- docWatchers.push_back(w);
-
- if (grad->isSwatch()) {
-
- for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) {
- StopWatcher* sw = new StopWatcher(this, s);
- docWatchers.push_back(sw);
- }
+ _currentDesktop->selection->connectModified(
+ sigc::hide(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))));
- if (_storeDoc && rowiter) {
- Gtk::TreeModel::iterator iter = _storeDoc->append(rowiter->children());
- Gtk::TreeModel::Row row = *iter;
- row[_modelDoc->_colObject] = grad;
- row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId();
- GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18);
- row[_modelDoc->_colPixbuf] = Glib::wrap(pixb);
+ _currentDesktop->connectToolSubselectionChanged(
+ sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
- _editDoc.expand_to_path(_storeDoc->get_path(iter));
- }
+ 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 );
- item = Gtk::manage(new ColorItem(grad, cit->label() ? cit->label() : cit->getId(), _currentDesktop));
- item->signal_button_press_event().connect_notify(sigc::bind<SPGradient *>(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad));
- item->set_tooltip_text(cit->label() ? cit->label() : cit->getId());
- if (_showlabels) {
- _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ );
- } else {
- _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ );
- }
- i++;
- }
- }
- }
- }
- }
+ _setDocument( desktop->doc() );
+ } else {
+ _setDocument(0);
}
}
- //_scroller.resize(1,1);
- _insideTable.resize(1,1);
- _scroller.show_all_children();
- _scroller.queue_draw();
-
}
-Gtk::MenuItem* SwatchesPanel::_addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow)
+
+class DocTrack
{
- Gtk::MenuItem* mi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId(),1));
- Gtk::Menu* m = NULL;
-
- Gtk::TreeModel::Row* r;
- if (_store) {
- Gtk::TreeModel::iterator iter = parentRow ? _store->append(parentRow->children()) : _store->append();
- Gtk::TreeModel::Row row = *iter;
- row[_model->_colObject] = group;
- row[_model->_colLabel] = group->label() ? group->label() : group->getId();
-
- if (SP_IS_GROUP(group->parent) && SP_GROUP(group->parent)->expanded()) {
- _editBI.expand_to_path(_store->get_path(iter));
+public:
+ DocTrack(SPDocument *doc, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) :
+ doc(doc->doRef()),
+ updatePending(false),
+ lastGradientUpdate(0.0),
+ gradientRsrcChanged(gradientRsrcChanged),
+ defsChanged(defsChanged),
+ defsModified(defsModified)
+ {
+ if ( !timer ) {
+ timer = new Glib::Timer();
+ refreshTimer = Glib::signal_timeout().connect( sigc::ptr_fun(handleTimerCB), 33 );
}
- r = &row;
- } else {
- r = NULL;
+ timerRefCount++;
}
-
- bool hasswatches = false;
- for (SPObject * obj = group->firstChild(); obj != NULL; obj = obj->next)
+
+ ~DocTrack()
{
- if (SP_IS_GROUP(obj)) {
- if (!m) {
- m = manage(new Gtk::Menu());
- m->show_all();
- mi->set_submenu(*m);
-
- Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(_("[All]")));
- basemi->show();
- Gtk::Label* namelbl = dynamic_cast<Gtk::Label*>(basemi->get_child());
- if (namelbl) {
- namelbl->set_markup(_("<b>[All]</b>"));
- }
- basemi->signal_activate().connect(sigc::bind<SPGroup*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, true));
- m->append(*basemi);
-
- Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- m->append(*sep);
+ timerRefCount--;
+ if ( timerRefCount <= 0 ) {
+ refreshTimer.disconnect();
+ timerRefCount = 0;
+ if ( timer ) {
+ timer->stop();
+ delete timer;
+ timer = 0;
}
- SwatchWatcher* w = new SwatchWatcher(this, obj, true);
- rootWatchers.push_back(w);
- m->append(*_addSwatchGroup(SP_GROUP(obj), r));
- } else if (SP_IS_GRADIENT(obj)) {
- hasswatches = true;
}
- }
- if (!m) {
- mi->signal_activate().connect(sigc::bind<SPGroup*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false));
- } else if (hasswatches) {
- Glib::ustring us = Glib::ustring::compose("<b>%1</b>", group->label() ? group->label() : group->getId());
- Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId()));
- basemi->show();
- Gtk::Label* namelbl = dynamic_cast<Gtk::Label*>(basemi->get_child());
- if (namelbl) {
- namelbl->set_markup(us);
+ if (doc) {
+ gradientRsrcChanged.disconnect();
+ defsChanged.disconnect();
+ defsModified.disconnect();
+ doc->doUnref();
+ doc = NULL;
}
- basemi->signal_activate().connect(sigc::bind<SPGroup*, bool>(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false));
- m->prepend(*basemi);
}
- mi->show();
- return mi;
-}
-void SwatchesPanel::_swatchesChanged()
-{
- while (!rootWatchers.empty()) {
- Inkscape::XML::NodeObserver* w = rootWatchers.back();
- rootWatchers.pop_back();
- delete w;
- }
+ static bool handleTimerCB();
- std::vector<Gtk::Widget *> menuChildren = popUpMenu->get_children();
- for (std::vector<Gtk::Widget *>::iterator c = menuChildren.begin(); c != menuChildren.end(); ++c) {
- popUpMenu->remove(**c);
- }
-
- if (_store) {
- _store->clear();
- }
-
- Gtk::MenuItem* mi;
-
- for (SPObject * obj = SwatchDocument->getDefs()->firstChild(); obj != NULL; obj = obj->next)
- {
- if (SP_IS_GROUP(obj)) {
- SwatchWatcher* w = new SwatchWatcher(this, obj, true);
- rootWatchers.push_back(w);
- popUpMenu->append(*_addSwatchGroup(SP_GROUP(obj), NULL));
-
- }
- }
- Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem());
- sep->show();
- popUpMenu->append(*sep);
-
- mi = manage(new Gtk::MenuItem(_("New Swatch Group..."),1));
- mi->signal_activate().connect(sigc::mem_fun(*this, &SwatchesPanel::NewGroup));
- mi->show();
- popUpMenu->append(*mi);
-
- mi = manage(new Gtk::MenuItem(_("Add Swatch File..."),1));
- mi->signal_activate().connect(sigc::bind<bool, bool>(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, false));
- mi->show();
- popUpMenu->append(*mi);
-
- mi = manage(new Gtk::MenuItem(_("Import Swatch File..."),1));
- mi->signal_activate().connect(sigc::bind<bool, bool>(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, true));
- mi->show();
- popUpMenu->append(*mi);
-}
+ /**
+ * Checks if update should be queued or executed immediately.
+ *
+ * @return true if the update was queued and should not be immediately executed.
+ */
+ static bool queueUpdateIfNeeded(SPDocument *doc);
-void SwatchesPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback )
+ static Glib::Timer *timer;
+ static int timerRefCount;
+ static sigc::connection refreshTimer;
+
+ SPDocument *doc;
+ bool updatePending;
+ double lastGradientUpdate;
+ sigc::connection gradientRsrcChanged;
+ sigc::connection defsChanged;
+ sigc::connection defsModified;
+
+private:
+ DocTrack(DocTrack const &); // no copy
+ DocTrack &operator=(DocTrack const &); // no assign
+};
+
+Glib::Timer *DocTrack::timer = 0;
+int DocTrack::timerRefCount = 0;
+sigc::connection DocTrack::refreshTimer;
+
+static const double DOC_UPDATE_THREASHOLD = 0.090;
+
+bool DocTrack::handleTimerCB()
{
- bool set = false;
-
- if ( iconName ) {
- GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
- gtk_widget_show( child );
- btn.add( *manage(Glib::wrap(child)) );
- btn.set_relief(Gtk::RELIEF_NONE);
- set = true;
- }
+ double now = timer->elapsed();
- if ( desktop ) {
- Verb *verb = Verb::get( code );
- if ( verb ) {
- SPAction *action = verb->get_action(desktop);
- if ( !set && action && action->image ) {
- GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image );
- gtk_widget_show( child );
- btn.add( *manage(Glib::wrap(child)) );
- set = true;
- }
+ std::vector<DocTrack *> needCallback;
+ for (std::vector<DocTrack *>::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) {
+ DocTrack *track = *it;
+ if ( track->updatePending && ( (now - track->lastGradientUpdate) >= DOC_UPDATE_THREASHOLD) ) {
+ needCallback.push_back(track);
}
}
-
- btn.set_tooltip_text (fallback);
-
- if ( !set ) {
- btn.set_label( fallback );
- }
-}
-void SwatchesPanel::_addButtonClicked(GdkEventButton* event) {
- if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3 || event->button == 1) ) {
- if (popUpMenu) {
- popUpMenu->popup(event->button, event->time);
+ for (std::vector<DocTrack *>::iterator it = needCallback.begin(); it != needCallback.end(); ++it) {
+ DocTrack *track = *it;
+ if ( std::find(docTrackings.begin(), docTrackings.end(), track) != docTrackings.end() ) { // Just in case one gets deleted while we are looping
+ // Note: calling handleDefsModified will call queueUpdateIfNeeded and thus update the time and flag.
+ SwatchesPanel::handleDefsModified(track->doc);
}
}
-}
-void SwatchesPanel::NoLinkToggled() {
- static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- Glib::ustring nolink = Glib::ustring::compose("%1/nolink", _prefs_path);
- prefs->setBool(nolink, _noLink.get_active());
+ return true;
}
-bool SwatchesPanel::_handleButtonEvent(GdkEventButton *event)
+bool DocTrack::queueUpdateIfNeeded( SPDocument *doc )
{
- static unsigned doubleclick = 0;
- if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
- doubleclick = 1;
- }
+ bool deferProcessing = false;
+ for (std::vector<DocTrack*>::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) {
+ DocTrack *track = *it;
+ if ( track->doc == doc ) {
+ double now = timer->elapsed();
+ double elapsed = now - track->lastGradientUpdate;
+
+ if ( elapsed < DOC_UPDATE_THREASHOLD ) {
+ deferProcessing = true;
+ track->updatePending = true;
+ } else {
+ track->lastGradientUpdate = now;
+ track->updatePending = false;
+ }
- if ( event->type == GDK_BUTTON_RELEASE && doubleclick) {
- doubleclick = 0;
- Gtk::TreeModel::Path path;
- Gtk::TreeViewColumn* col = 0;
- int x = static_cast<int>(event->x);
- int y = static_cast<int>(event->y);
- int x2 = 0;
- int y2 = 0;
- if ( _editBI.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnBI) {
- // Double click on the Layer name, enable editing
- _text_rendererBI->property_editable() = true;
- _editBI.set_cursor (path, *_name_columnBI, true);
- grab_focus();
+ break;
}
}
-
- return false;
+ return deferProcessing;
}
-bool SwatchesPanel::_handleKeyEvent(GdkEventKey *event)
+void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document )
{
- switch (Inkscape::UI::Tools::get_group0_keyval(event)) {
- case GDK_KEY_Return:
- case GDK_KEY_KP_Enter:
- case GDK_KEY_F2: {
- Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected();
- if (iter && !_text_rendererBI->property_editable()) {
- Gtk::TreeRow row = *iter;
- SPObject * obj = row[_model->_colObject];
- if (obj) {
- Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter);
- // Edit the layer label
- _text_rendererBI->property_editable() = true;
- _editBI.set_cursor(*path, *_name_columnBI, true);
- grab_focus();
- return true;
+ SPDocument *oldDoc = NULL;
+ if (docPerPanel.find(panel) != docPerPanel.end()) {
+ oldDoc = docPerPanel[panel];
+ if (!oldDoc) {
+ docPerPanel.erase(panel); // Should not be needed, but clean up just in case.
+ }
+ }
+ if (oldDoc != document) {
+ if (oldDoc) {
+ docPerPanel[panel] = NULL;
+ bool found = false;
+ for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) {
+ found = (it->second == document);
+ }
+ if (!found) {
+ for (std::vector<DocTrack*>::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){
+ if ((*it)->doc == oldDoc) {
+ delete *it;
+ docTrackings.erase(it);
+ break;
+ }
}
}
}
- case GDK_KEY_Delete: {
-
- Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected();
- if (iter) {
- Gtk::TreeRow row = *iter;
- SPObject * obj = row[_model->_colObject];
- if (obj) {
- obj->deleteObject(false);
- sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
+
+ if (document) {
+ bool found = false;
+ for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) {
+ found = (it->second == document);
+ }
+ docPerPanel[panel] = document;
+ if (!found) {
+ sigc::connection conn1 = document->connectResourcesChanged( "gradient", sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleGradientsChange), document) );
+ sigc::connection conn2 = document->getDefs()->connectRelease( sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document)) );
+ sigc::connection conn3 = document->getDefs()->connectModified( sigc::hide(sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document))) );
+
+ DocTrack *dt = new DocTrack(document, conn1, conn2, conn3);
+ docTrackings.push_back(dt);
+
+ if (docPalettes.find(document) == docPalettes.end()) {
+ SwatchPage *docPalette = new SwatchPage();
+ docPalette->_name = "Auto";
+ docPalettes[document] = docPalette;
}
}
- return true;
}
- break;
}
- return false;
}
-void SwatchesPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text)
+void SwatchesPanel::_setDocument( SPDocument *document )
{
- Gtk::TreeModel::iterator iter = _editBI.get_model()->get_iter(path);
- Gtk::TreeModel::Row row = *iter;
-
- _renameObject(row, new_text);
- _text_rendererBI->property_editable() = false;
+ if ( document != _currentDocument ) {
+ _trackDocument(this, document);
+ _currentDocument = document;
+ handleGradientsChange( document );
+ }
}
-void SwatchesPanel::_handleEditingCancelled()
+static void recalcSwatchContents(SPDocument* doc,
+ boost::ptr_vector<ColorItem> &tmpColors,
+ std::map<ColorItem*, cairo_pattern_t*> &previewMappings,
+ std::map<ColorItem*, SPGradient*> &gradMappings)
{
- _text_rendererBI->property_editable() = false;
-}
+ std::vector<SPGradient*> newList;
-void SwatchesPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name)
-{
- if ( row && SwatchDocument) {
- SPObject* obj = row[_model->_colObject];
- if ( obj ) {
- gchar const* oldLabel = obj->label();
- if ( !name.empty() && (!oldLabel || name != oldLabel) ) {
- obj->setLabel(name.c_str());
- sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
- }
+ const GSList *gradients = doc->getResourceList("gradient");
+ for (const GSList *item = gradients; item; item = item->next) {
+ SPGradient* grad = SP_GRADIENT(item->data);
+ if ( grad->isSwatch() ) {
+ newList.push_back(SP_GRADIENT(item->data));
}
}
-}
-void SwatchesPanel::_setCollapsed(SPGroup * group)
-{
- group->setExpanded(false);
- group->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
- for (SPObject *iter = group->children; iter != NULL; iter = iter->next)
- {
- if (SP_IS_GROUP(iter)) _setCollapsed(SP_GROUP(iter));
- }
-}
+ if ( !newList.empty() ) {
+ std::reverse(newList.begin(), newList.end());
+ for ( std::vector<SPGradient*>::iterator it = newList.begin(); it != newList.end(); ++it )
+ {
+ SPGradient* grad = *it;
-void SwatchesPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded)
-{
- Gtk::TreeModel::Row row = *iter;
+ cairo_surface_t *preview = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ PREVIEW_PIXBUF_WIDTH, VBLOCK);
+ cairo_t *ct = cairo_create(preview);
- SPObject* obj = row[_model->_colObject];
- if (obj && SP_IS_GROUP(obj))
- {
- if (isexpanded)
- {
- SP_GROUP(obj)->setExpanded(isexpanded);
- obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
- }
- else
- {
- _setCollapsed(SP_GROUP(obj));
- }
- }
- sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
-}
+ Glib::ustring name( grad->getId() );
+ ColorItem* item = new ColorItem( 0, 0, 0, name );
-void SwatchesPanel::_deleteButtonClicked()
-{
- Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected();
- if (iter) {
- Gtk::TreeModel::Row row = *iter;
- SPObject* obj = row[_model->_colObject];
- if (obj) {
- obj->deleteObject(false);
- sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
+ cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
+ cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(grad, PREVIEW_PIXBUF_WIDTH);
+ cairo_set_source(ct, check);
+ cairo_paint(ct);
+ cairo_set_source(ct, gradient);
+ cairo_paint(ct);
+
+ cairo_destroy(ct);
+ cairo_pattern_destroy(gradient);
+ cairo_pattern_destroy(check);
+
+ cairo_pattern_t *prevpat = cairo_pattern_create_for_surface(preview);
+ cairo_surface_destroy(preview);
+
+ previewMappings[item] = prevpat;
+
+ tmpColors.push_back(item);
+ gradMappings[item] = grad;
}
}
}
-bool SwatchesPanel::_handleButtonEventDoc(GdkEventButton* event)
+void SwatchesPanel::handleGradientsChange(SPDocument *document)
{
- static unsigned doubleclick = 0;
-
- if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) {
- // TODO - fix to a better is-popup function
- Gtk::TreeModel::Path path;
- int x = static_cast<int>(event->x);
- int y = static_cast<int>(event->y);
- if ( _editDoc.get_path_at_pos( x, y, path ) ) {
- Gtk::TreeModel::Children::iterator iter = _editDoc.get_model()->get_iter(path);
- Gtk::TreeModel::Row row = *iter;
-
- SPObject* obj = row[_modelDoc->_colObject];
- if (SP_IS_GRADIENT(obj)) {
- _swatchClicked(event, SP_GRADIENT(obj));
- } else if (SP_IS_GROUP(obj)) {
- _lblClick(event, SP_GROUP(obj));
- } else {
- _lblClick(event, NULL);
- }
- } else {
- _lblClick(event, NULL);
- }
- }
-
- if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
- doubleclick = 1;
- }
+ SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0;
+ if (docPalette) {
+ boost::ptr_vector<ColorItem> tmpColors;
+ std::map<ColorItem*, cairo_pattern_t*> tmpPrevs;
+ std::map<ColorItem*, SPGradient*> tmpGrads;
+ recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads);
- if ( event->type == GDK_BUTTON_RELEASE && doubleclick) {
- doubleclick = 0;
- Gtk::TreeModel::Path path;
- Gtk::TreeViewColumn* col = 0;
- int x = static_cast<int>(event->x);
- int y = static_cast<int>(event->y);
- int x2 = 0;
- int y2 = 0;
- if ( _editDoc.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnDoc) {
- // Double click on the Layer name, enable editing
- _text_rendererDoc->property_editable() = true;
- _editDoc.set_cursor (path, *_name_columnDoc, true);
- grab_focus();
+ for (std::map<ColorItem*, cairo_pattern_t*>::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) {
+ it->first->setPattern(it->second);
+ cairo_pattern_destroy(it->second);
}
- }
-
- return false;
-}
-void SwatchesPanel::_deleteButtonClickedDoc()
-{
- Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected();
- if (iter) {
- Gtk::TreeRow row = *iter;
- SPObject * obj = row[_modelDoc->_colObject];
- if (SP_IS_GRADIENT(obj)) {
- RemoveSwatch(SP_GRADIENT(obj));
- } else if (SP_IS_GROUP(obj)) {
- Remove(SP_GROUP(obj));
+ for (std::map<ColorItem*, SPGradient*>::iterator it = tmpGrads.begin(); it != tmpGrads.end(); ++it) {
+ it->first->setGradient(it->second);
}
- }
-}
-bool SwatchesPanel::_handleKeyEventDoc(GdkEventKey *event)
-{
- switch (Inkscape::UI::Tools::get_group0_keyval(event)) {
- case GDK_KEY_Return:
- case GDK_KEY_KP_Enter:
- case GDK_KEY_F2: {
- Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected();
- if (iter && !_text_rendererDoc->property_editable()) {
- Gtk::TreeRow row = *iter;
- SPObject * obj = row[_modelDoc->_colObject];
- if (obj) {
- Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter);
- // Edit the layer label
- _text_rendererDoc->property_editable() = true;
- _editDoc.set_cursor(*path, *_name_columnDoc, true);
- grab_focus();
- return true;
+ docPalette->_colors.swap(tmpColors);
+
+ // Figure out which SwatchesPanel instances are affected and update them.
+
+ for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) {
+ if (it->second == document) {
+ SwatchesPanel* swp = it->first;
+ std::vector<SwatchPage*> pages = swp->_getSwatchSets();
+ SwatchPage* curr = pages[swp->_currentIndex];
+ if (curr == docPalette) {
+ swp->_rebuild();
}
}
}
- case GDK_KEY_Delete: {
-
- _deleteButtonClickedDoc();
- return true;
- }
- break;
}
- return false;
}
-void SwatchesPanel::_renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name)
+void SwatchesPanel::handleDefsModified(SPDocument *document)
{
- if ( row && SwatchDocument) {
- SPObject* obj = row[_modelDoc->_colObject];
- if ( obj ) {
- gchar const* oldLabel = obj->label();
- if ( !name.empty() && (!oldLabel || name != oldLabel) ) {
- obj->setLabel(name.c_str());
+ SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0;
+ if (docPalette && !DocTrack::queueUpdateIfNeeded(document) ) {
+ boost::ptr_vector<ColorItem> tmpColors;
+ std::map<ColorItem*, cairo_pattern_t*> tmpPrevs;
+ std::map<ColorItem*, SPGradient*> tmpGrads;
+ recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads);
+
+ if ( tmpColors.size() != docPalette->_colors.size() ) {
+ handleGradientsChange(document);
+ } else {
+ int cap = std::min(docPalette->_colors.size(), tmpColors.size());
+ for (int i = 0; i < cap; i++) {
+ ColorItem *newColor = &tmpColors[i];
+ ColorItem *oldColor = &docPalette->_colors[i];
+ if ( (newColor->def.getType() != oldColor->def.getType()) ||
+ (newColor->def.getR() != oldColor->def.getR()) ||
+ (newColor->def.getG() != oldColor->def.getG()) ||
+ (newColor->def.getB() != oldColor->def.getB()) ) {
+ oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB());
+ }
+ if (tmpGrads.find(newColor) != tmpGrads.end()) {
+ oldColor->setGradient(tmpGrads[newColor]);
+ }
+ if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) {
+ oldColor->setPattern(tmpPrevs[newColor]);
+ }
}
}
- }
-}
-
-void SwatchesPanel::_handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text)
-{
- Gtk::TreeModel::iterator iter = _editDoc.get_model()->get_iter(path);
- Gtk::TreeModel::Row row = *iter;
- _renameObjectDoc(row, new_text);
- _text_rendererDoc->property_editable() = false;
+ for (std::map<ColorItem*, cairo_pattern_t*>::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) {
+ cairo_pattern_destroy(it->second);
+ }
+ }
}
-void SwatchesPanel::_handleEditingCancelledDoc()
-{
- _text_rendererDoc->property_editable() = false;
-}
-/*
- * Drap and drop within the tree
- * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer
- */
-bool SwatchesPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time)
+std::vector<SwatchPage*> SwatchesPanel::_getSwatchSets() const
{
- int cell_x = 0, cell_y = 0;
- Gtk::TreeModel::Path target_path;
- Gtk::TreeView::Column *target_column;
-
- bool _dnd_top = false;
- _dnd_into = false;
- _dnd_target = SwatchDocument->getDefs()->lastChild();
- Gtk::TreeModel::iterator itersel = _editBI.get_selection()->get_selected();
- if (!itersel) {
- return true;
+ std::vector<SwatchPage*> tmp;
+ if (docPalettes.find(_currentDocument) != docPalettes.end()) {
+ tmp.push_back(docPalettes[_currentDocument]);
}
- Gtk::TreeModel::Row rowsel = *itersel;
- _dnd_source = rowsel[_model->_colObject];
- if (!_dnd_source) {
- return true;
- }
-
- if (_editBI.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) {
- // Are we before, inside or after the drop layer
- Gdk::Rectangle rect;
- _editBI.get_background_area (target_path, *target_column, rect);
- int cell_height = rect.get_height();
- _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3));
- if (cell_y < (int)(cell_height * 1/3)) {
- Gtk::TreeModel::Path next_path = target_path;
- if (next_path.prev()) {
- target_path = next_path;
- } else {
- // Dragging to the "end"
- Gtk::TreeModel::Path up_path = target_path;
- up_path.up();
- if (_store->iter_is_valid(_store->get_iter(up_path))) {
- // Drop into parent
- target_path = up_path;
- _dnd_into = true;
- } else {
- _dnd_top = true;
- // Drop into the top level
- _dnd_target = NULL;
- }
- }
- }
- if (!_dnd_top) {
- Gtk::TreeModel::iterator iter = _store->get_iter(target_path);
- if (_store->iter_is_valid(iter)) {
- Gtk::TreeModel::Row row = *iter;
- SPObject *obj = row[_model->_colObject];
- if (obj) {
- _dnd_target = obj;
- }
- }
- }
- }
-
- if (_dnd_source != _dnd_target) {
-
- Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL;
- Inkscape::XML::Node *our_ref = _dnd_source->getRepr();
-
- if (target_ref != our_ref) {
- if (!target_ref) {
- target_ref = SwatchDocument->getDefs()->getRepr();
- if (target_ref != our_ref->parent()) {
- our_ref->parent()->removeChild(our_ref);
- target_ref->addChild(our_ref, NULL);
- } else {
- our_ref->parent()->changeOrder(our_ref, NULL);
- }
- } else if (_dnd_into) {
- // Move this inside of the target at the end
- our_ref->parent()->removeChild(our_ref);
- target_ref->addChild(our_ref, NULL);
- } else if (target_ref->parent() != our_ref->parent()) {
- // Change in parent, need to remove and add
- our_ref->parent()->removeChild(our_ref);
- target_ref->parent()->addChild(our_ref, target_ref);
- } else {
- // Same parent, just move
- our_ref->parent()->changeOrder(our_ref, target_ref);
- }
- }
- sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI);
- }
+ tmp.insert(tmp.end(), userSwatchPages.begin(), userSwatchPages.end());
+ tmp.insert(tmp.end(), systemSwatchPages.begin(), systemSwatchPages.end());
- return true;
+ return tmp;
}
-/*
- * Drap and drop within the tree
- * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer
- */
-bool SwatchesPanel::_handleDragDropDoc(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time)
+void SwatchesPanel::_updateFromSelection()
{
- int cell_x = 0, cell_y = 0;
- Gtk::TreeModel::Path target_path;
- Gtk::TreeView::Column *target_column;
-
- bool _dnd_top = false;
- _dnd_into = false;
- _dnd_target = _currentDocument->getDefs()->lastChild();
- Gtk::TreeModel::iterator itersel = _editDoc.get_selection()->get_selected();
- if (!itersel) {
- return true;
- }
- Gtk::TreeModel::Row rowsel = *itersel;
- _dnd_source = rowsel[_modelDoc->_colObject];
-
- if (!_dnd_source) {
- return true;
- }
-
- if (_editDoc.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) {
- // Are we before, inside or after the drop layer
- Gdk::Rectangle rect;
- _editDoc.get_background_area (target_path, *target_column, rect);
- int cell_height = rect.get_height();
- _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3));
- if (cell_y < (int)(cell_height * 1/3)) {
- Gtk::TreeModel::Path next_path = target_path;
- if (next_path.prev()) {
- target_path = next_path;
- } else {
- // Dragging to the "end"
- Gtk::TreeModel::Path up_path = target_path;
- up_path.up();
- if (_storeDoc->iter_is_valid(_storeDoc->get_iter(up_path))) {
- // Drop into parent
- target_path = up_path;
- _dnd_into = true;
- } else {
- _dnd_top = true;
- // Drop into the top level
- _dnd_target = NULL;
+ SwatchPage *docPalette = (docPalettes.find(_currentDocument) != docPalettes.end()) ? docPalettes[_currentDocument] : 0;
+ if ( docPalette ) {
+ 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->isSwatch() ) {
+ target = grad;
+ } else if ( grad->ref ) {
+ SPGradient *tmp = grad->ref->getObject();
+ if ( tmp && tmp->isSwatch() ) {
+ target = tmp;
+ }
+ }
+ if ( target ) {
+ //XML Tree being used directly here while it shouldn't be
+ gchar const* id = target->getRepr()->attribute("id");
+ if ( id ) {
+ fillId = id;
+ }
+ }
+ }
}
+ break;
}
}
- if (!_dnd_top) {
- Gtk::TreeModel::iterator iter = _storeDoc->get_iter(target_path);
- if (_storeDoc->iter_is_valid(iter)) {
- Gtk::TreeModel::Row row = *iter;
- SPObject *obj = row[_modelDoc->_colObject];
- if (obj) {
- _dnd_target = obj;
- if (SP_IS_GRADIENT(obj)) {
- _dnd_into = false;
- if (SP_IS_GROUP(_dnd_source)) {
- _dnd_target = obj->parent;
+
+ 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->isSwatch() ) {
+ target = grad;
+ } else if ( grad->ref ) {
+ SPGradient *tmp = grad->ref->getObject();
+ if ( tmp && tmp->isSwatch() ) {
+ target = tmp;
+ }
+ }
+ if ( target ) {
+ //XML Tree being used directly here while it shouldn't be
+ gchar const* id = target->getRepr()->attribute("id");
+ if ( id ) {
+ strokeId = id;
+ }
}
- } else if (SP_IS_GROUP(_dnd_source)) {
- _dnd_into = false;
}
}
+ break;
}
}
- }
-
- if (_dnd_source != _dnd_target) {
-
- Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL;
- Inkscape::XML::Node *our_ref = _dnd_source->getRepr();
-
- if (target_ref != our_ref) {
- if (!target_ref) {
- target_ref = _currentDocument->getDefs()->getRepr();
- if (target_ref != our_ref->parent()) {
- our_ref->parent()->removeChild(our_ref);
- target_ref->addChild(our_ref, NULL);
- } else {
- our_ref->parent()->changeOrder(our_ref, NULL);
- }
- } else if (_dnd_into) {
- // Move this inside of the target at the end
- our_ref->parent()->removeChild(our_ref);
- target_ref->addChild(our_ref, NULL);
- } else if (target_ref->parent() != our_ref->parent()) {
- // Change in parent, need to remove and add
- our_ref->parent()->removeChild(our_ref);
- target_ref->parent()->addChild(our_ref, target_ref);
- } else {
- // Same parent, just move
- our_ref->parent()->changeOrder(our_ref, target_ref);
- }
+ sp_style_unref(tmpStyle);
+
+ for ( boost::ptr_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 );
}
- DocumentUndo::done( _currentDocument , SP_VERB_DIALOG_SWATCHES,
- _("Moved Swatches"));
}
-
- return true;
}
-
-/**
- * Constructor
- */
-SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) :
- Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, ""),
- _scroller(),
- _insideTable(1, 1),
- _insideV(),
- _insideH(),
- _buttonsRow(),
- _outsideV(),
- _noLink(_("Don't Link")),
- _showlabels(showLabels),
- _store(0),
- _scrollerBI(),
- _editBI(),
- _buttonsRowBI(),
- _editBIV(),
- _storeDoc(0),
- _scrollerDoc(),
- _editDoc(),
- _buttonsRowDoc(),
- _editDocV(),
- _notebook(),
- rootWatcher(0),
- docWatcher(0),
- _currentDesktop(0),
- _currentDocument(0)
+void SwatchesPanel::_handleAction( int setId, int itemId )
{
- _insideH.pack_start(_insideTable, Gtk::PACK_SHRINK);
- if (_showlabels) {
- _insideV.pack_start(_insideH, Gtk::PACK_SHRINK);
- _scroller.add(_insideV);
- } else {
- _scroller.property_height_request() = 20;
- _scroller.add(_insideH);
- }
-
- popUpMenu = manage( new Gtk::Menu() );
- popUpMenu->show_all_children();
-
- Gtk::Button* btn = manage( new Gtk::Button() );
- _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Add Swatch") );
- btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked) );
- _buttonsRow.pack_start(*btn, Gtk::PACK_SHRINK);
-
-// btn = manage( new Gtk::Button() );
-// _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_DISCONNECT, C_("Unlink", "New") );
-// _buttonsRow.pack_end(*btn, Gtk::PACK_SHRINK);
-
- static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- Glib::ustring nolink = Glib::ustring::compose("%1/nolink", prefsPath);
- _noLink.set_tooltip_text(_("Don't link swatches"));
- _noLink.set_active(prefs->getBool(nolink, false));
- _noLink.signal_toggled().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NoLinkToggled));
- _buttonsRow.pack_end(_noLink, Gtk::PACK_SHRINK);
-
- _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
- _scroller.set_shadow_type(Gtk::SHADOW_NONE);
-
- if (_showlabels) {
- _outsideV.pack_end(_buttonsRow, Gtk::PACK_SHRINK);
- _outsideV.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET);
-
- _notebook.append_page(_outsideV, "Use");
-
+ switch( setId ) {
+ case 3:
{
- ModelColumnsDoc *zoop = new ModelColumnsDoc();
- _modelDoc = zoop;
-
- _storeDoc = Gtk::TreeStore::create( *zoop );
-
- _editDoc.set_model( _storeDoc );
- _editDoc.set_headers_visible(false);
- _editDoc.set_reorderable(true);
- _editDoc.enable_model_drag_dest (Gdk::ACTION_MOVE);
-
- Gtk::Button* btn = manage( new Gtk::Button() );
- _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") );
- btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked));
- _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK);
-
- btn = manage( new Gtk::Button() );
- _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") );
- btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClickedDoc)));
- _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK);
-
- _pixbuf_rendererDoc = manage(new Gtk::CellRendererPixbuf());
- int pixbufColNum = _editDoc.append_column("Pixbuf", *_pixbuf_rendererDoc) - 1;
- _pixbuf_columnDoc = _editDoc.get_column(pixbufColNum);
- _pixbuf_columnDoc->add_attribute(_pixbuf_rendererDoc->property_pixbuf(), _modelDoc->_colPixbuf);
-
- _text_rendererDoc = manage(new Gtk::CellRendererText());
- int nameColNum = _editDoc.append_column("Name", *_text_rendererDoc) - 1;
- _name_columnDoc = _editDoc.get_column(nameColNum);
- _name_columnDoc->add_attribute(_text_rendererDoc->property_text(), _modelDoc->_colLabel);
-
- _text_rendererDoc->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditedDoc) );
- _text_rendererDoc->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelledDoc) );
-
- _editDoc.set_expander_column( *_editDoc.get_column(nameColNum) );
+ std::vector<SwatchPage*> pages = _getSwatchSets();
+ if ( itemId >= 0 && itemId < static_cast<int>(pages.size()) ) {
+ _currentIndex = itemId;
- _editDoc.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false );
- _editDoc.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false );
- _editDoc.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEventDoc), false );
-
- _editDoc.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDropDoc), false);
-
- _scrollerDoc.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
- _scrollerDoc.set_shadow_type(Gtk::SHADOW_IN);
- _scrollerDoc.add(_editDoc);
-
- _editDocV.pack_start(_scrollerDoc, Gtk::PACK_EXPAND_WIDGET);
- _editDocV.pack_end(_buttonsRowDoc, Gtk::PACK_SHRINK);
+ if ( !_prefs_path.empty() ) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setString(_prefs_path + "/palette", pages[_currentIndex]->_name);
+ }
- _notebook.append_page(_editDocV, "Edit");
- }
-
- {
- popUpImportMenu = Gtk::manage(new Gtk::Menu());
-
- Gtk::MenuItem* mi = Gtk::manage(new Gtk::MenuItem(_("New Swatch Group...")));
- mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroupBI));
- mi->show();
- popUpImportMenu->append(*mi);
-
- mi = Gtk::manage(new Gtk::MenuItem(_("Import Swatch File...")));
- mi->signal_activate().connect_notify(sigc::bind<bool, bool>(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), false, true));
- mi->show();
- popUpImportMenu->append(*mi);
-
- ModelColumns *zoop = new ModelColumns();
- _model = zoop;
-
- _store = Gtk::TreeStore::create( *zoop );
-
- _editBI.set_model( _store );
- _editBI.set_headers_visible(false);
- _editBI.set_reorderable(true);
- _editBI.enable_model_drag_dest (Gdk::ACTION_MOVE);
-
- Gtk::Button* btn = manage( new Gtk::Button() );
- _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") );
- btn->signal_button_press_event().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::_addBIButtonClicked));
- _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK);
-
- btn = manage( new Gtk::Button() );
- _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") );
- btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClicked)));
- _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK);
-
- _text_rendererBI = manage(new Gtk::CellRendererText());
- int nameColNum = _editBI.append_column("Name", *_text_rendererBI) - 1;
- _name_columnBI = _editBI.get_column(nameColNum);
- _name_columnBI->add_attribute(_text_rendererBI->property_text(), _model->_colLabel);
-
- _text_rendererBI->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEdited) );
- _text_rendererBI->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelled) );
-
- _editBI.set_expander_column( *_editBI.get_column(nameColNum) );
-
- _editBI.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false );
- _editBI.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false );
- _editBI.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEvent), false );
-
- _editBI.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDrop), false);
- _editBI.signal_row_collapsed().connect( sigc::bind<bool>(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), false));
- _editBI.signal_row_expanded().connect( sigc::bind<bool>(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), true));
-
- _scrollerBI.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
- _scrollerBI.set_shadow_type(Gtk::SHADOW_IN);
- _scrollerBI.add(_editBI);
-
- _editBIV.pack_start(_scrollerBI, Gtk::PACK_EXPAND_WIDGET);
- _editBIV.pack_end(_buttonsRowBI, Gtk::PACK_SHRINK);
-
- _notebook.append_page(_editBIV, "Edit Built-In");
+ _rebuild();
+ }
}
-
- _getContents()->pack_end(_notebook, Gtk::PACK_EXPAND_WIDGET);
- } else {
- //_outsideV.pack_end(_scroller, Gtk::PACK_SHRINK);
- _buttonsRow.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET);
- //_getContents()->pack_end(_outsideV, Gtk::PACK_SHRINK);
- _getContents()->pack_end(_buttonsRow, Gtk::PACK_SHRINK);
- }
-
- loadPalletFile();
-
- rootWatcher = new SwatchWatcher(this, SwatchDocument->getDefs(), true);
- SwatchDocument->getDefs()->getRepr()->addObserver(*rootWatcher);
- _swatchesChanged();
- _insideTable.resize(1,1);
-}
-
-SwatchesPanel::~SwatchesPanel()
-{
- if (rootWatcher) {
- rootWatcher->_repr->removeObserver(*rootWatcher);
- delete rootWatcher;
- }
-
- if (docWatcher) {
- docWatcher->_repr->removeObserver(*docWatcher);
- delete docWatcher;
+ break;
}
-
- _documentConnection.disconnect();
- _selChanged.disconnect();
}
-void SwatchesPanel::setDesktop( SPDesktop* desktop )
+void SwatchesPanel::_rebuild()
{
- Inkscape::UI::Widget::Panel::setDesktop(desktop);
- if ( desktop != _currentDesktop ) {
- if ( _currentDesktop ) {
- _documentConnection.disconnect();
- _selChanged.disconnect();
- }
-
- _currentDesktop = desktop;
-
- if ( desktop ) {
- //_currentDesktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
+ std::vector<SwatchPage*> pages = _getSwatchSets();
+ SwatchPage* curr = pages[_currentIndex];
+ _holder->clear();
- _documentConnection = desktop->connectDocumentReplaced(sigc::mem_fun(*this, &SwatchesPanel::_setDocument));
-
- _setDocument( desktop, desktop->doc() );
- } else {
- _setDocument(0, 0);
- }
+ if ( curr->_prefWidth > 0 ) {
+ _holder->setColumnPref( curr->_prefWidth );
}
-}
-
-void SwatchesPanel::_setDocument( SPDesktop* desktop, SPDocument *document )
-{
- if ( document != _currentDocument ) {
- if (docWatcher) {
- docWatcher->_repr->removeObserver(*docWatcher);
- delete docWatcher;
- docWatcher = NULL;
- }
- _currentDocument = document;
-
- if (_currentDocument) {
- docWatcher = new SwatchWatcher(this, _currentDocument->getDefs(), false);
- _currentDocument->getDefs()->getRepr()->addObserver(*docWatcher);
- }
- _defsChanged();
+ _holder->freezeUpdates();
+ // TODO restore once 'clear' works _holder->addPreview(_clear);
+ _holder->addPreview(_remove);
+ for ( boost::ptr_vector<ColorItem>::iterator it = curr->_colors.begin(); it != curr->_colors.end(); ++it) {
+ _holder->addPreview(&*it);
}
+ _holder->thawUpdates();
}
} //namespace Dialogs
} //namespace UI
} //namespace Inkscape
-//really lazy!
-void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill)
-{
-
- bool intercepted = false;
-
- if (gradient->isSolid()) {
- ColorRGBA color(gradient->getFirstStop()->getEffectiveColor().toRGBA32(gradient->getFirstStop()->opacity));
- guint32 rgba = SP_RGBA32_F_COMPOSE(color[0], color[1], color[2], color[3]);
- gchar b[64];
- sp_svg_write_color(b, sizeof(b), rgba);
- SPCSSAttr *css = sp_repr_css_attr_new();
- if (fill) {
- sp_repr_css_set_property(css, "fill", b);
- Inkscape::CSSOStringStream osalpha;
- osalpha << color[3];
- sp_repr_css_set_property(css, "fill-opacity", osalpha.str().c_str());
- } else {
- sp_repr_css_set_property(css, "stroke", b);
- Inkscape::CSSOStringStream osalpha;
- osalpha << color[3];
- sp_repr_css_set_property(css, "stroke-opacity", osalpha.str().c_str());
- }
- intercepted = desktop->_set_style_signal.emit(css);
- }
-
- if (!intercepted) {
- for (const GSList *it = desktop->selection->itemList(); it != NULL; it = it->next) {
- sp_item_set_gradient(SP_ITEM(it->data), gradient, SP_IS_RADIALGRADIENT(gradient) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, !fill ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL);
- }
- }
-}
/*
Local Variables:
diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h
index cb8f87962..ca4c1687d 100644
--- a/src/ui/dialog/swatches.h
+++ b/src/ui/dialog/swatches.h
@@ -12,161 +12,64 @@
#include "ui/widget/panel.h"
#include "enums.h"
-#include "sp-object.h"
-#include "sp-item-group.h"
-#include <gtk/gtk.h>
-#include <gtkmm/radiomenuitem.h>
-#include <gtkmm/menuitem.h>
-#include <gtkmm/scrolledwindow.h>
-#include <gtkmm/table.h>
-#include <gtkmm/box.h>
-#include <gtkmm/menu.h>
-#include <gtkmm/notebook.h>
-#include <gtkmm/treeview.h>
-#include <gtkmm/treestore.h>
-#include <gtkmm/treemodel.h>
-#include "sp-gradient.h"
-#include "xml/node-observer.h"
namespace Inkscape {
namespace UI {
+class PreviewHolder;
+
namespace Dialogs {
+class ColorItem;
+class SwatchPage;
+class DocTrack;
+
/**
* A panel that displays paint swatches.
*/
class SwatchesPanel : public Inkscape::UI::Widget::Panel
{
public:
- SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches", bool showLabels = true);
+ SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches");
virtual ~SwatchesPanel();
-
+
static SwatchesPanel& getInstance();
+ virtual void setOrientation(SPAnchorType how);
+
virtual void setDesktop( SPDesktop* desktop );
virtual SPDesktop* getDesktop() {return _currentDesktop;}
+ virtual int getSelectedIndex() {return _currentIndex;} // temporary
+
protected:
+ static void handleGradientsChange(SPDocument *document);
+
+ virtual void _updateFromSelection();
+ virtual void _handleAction( int setId, int itemId );
+ virtual void _setDocument( SPDocument *document );
+ virtual void _rebuild();
- virtual void _setDocument( SPDesktop* desktop, SPDocument *document );
+ virtual std::vector<SwatchPage*> _getSwatchSets() const;
private:
- class ModelColumns;
- class ModelColumnsDoc;
-
- class StopWatcher;
- class GradientWatcher;
- class SwatchWatcher;
-
SwatchesPanel(SwatchesPanel const &); // no copy
SwatchesPanel &operator=(SwatchesPanel const &); // no assign
-
- void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback );
-
- void _setSelectionSwatch(SPGradient* swatchItem, bool isStroke);
-
- void NoLinkToggled();
- void NewGroup();
- void NewGroupBI();
- void _addBIButtonClicked(GdkEventButton* event);
- void Duplicate(SPGroup* page);
- void SaveAs();
- void AddSelectedFill(SPGroup* page);
- void AddSelectedStroke(SPGroup* page);
- void MoveUp(SPGroup* page);
- void MoveDown(SPGroup* page);
- void Remove(SPGroup* page);
-
- void SetSelectedFill(SPGradient* swatch);
- void SetSelectedStroke(SPGradient* swatch);
- void MoveSwatchUp(SPGradient* swatch);
- void MoveSwatchDown(SPGradient* swatch);
- void RemoveSwatch(SPGradient* swatch);
-
- void _lblClick(GdkEventButton* event, SPGroup* page);
- void _addSwatchButtonClicked(SPGroup* swatch, bool recurse);
- void _defsChanged();
- void _importButtonClicked(bool addToDoc, bool addToBI);
- void _deleteButtonClicked();
- void _addButtonClicked(GdkEventButton* event);
- void _swatchClicked(GdkEventButton* event, SPGradient* swatchItem);
-
- Gtk::MenuItem* _addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow);
- void _swatchesChanged();
-
- bool _handleButtonEvent(GdkEventButton *event);
- bool _handleKeyEvent(GdkEventKey *event);
-
- void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text);
- void _handleEditingCancelled();
- void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name);
-
- void _setCollapsed(SPGroup * group);
- void _setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded);
-
- void _deleteButtonClickedDoc();
- bool _handleButtonEventDoc(GdkEventButton* event);
- bool _handleKeyEventDoc(GdkEventKey *event);
-
- void _handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text);
- void _handleEditingCancelledDoc();
- void _renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name);
-
- bool _handleDragDropDoc(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
- bool _handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
-
- Gtk::Menu *popUpMenu;
- Gtk::Menu *popUpImportMenu;
-
- Gtk::ScrolledWindow _scroller;
- Gtk::Table _insideTable;
- Gtk::VBox _insideV;
- Gtk::HBox _insideH;
- Gtk::HBox _buttonsRow;
- Gtk::VBox _outsideV;
- Gtk::CheckButton _noLink;
- bool _showlabels;
-
- SwatchesPanel::ModelColumns* _model;
- Glib::RefPtr<Gtk::TreeStore> _store;
-
- Gtk::CellRendererText *_text_rendererBI;
- Gtk::TreeView::Column *_name_columnBI;
- Gtk::ScrolledWindow _scrollerBI;
- Gtk::TreeView _editBI;
- Gtk::HBox _buttonsRowBI;
- Gtk::VBox _editBIV;
-
- SwatchesPanel::ModelColumnsDoc* _modelDoc;
- Glib::RefPtr<Gtk::TreeStore> _storeDoc;
-
- Gtk::CellRendererText *_text_rendererDoc;
- Gtk::CellRendererPixbuf *_pixbuf_rendererDoc;
- Gtk::TreeView::Column *_name_columnDoc;
- Gtk::TreeView::Column *_pixbuf_columnDoc;
- Gtk::ScrolledWindow _scrollerDoc;
- Gtk::TreeView _editDoc;
- Gtk::HBox _buttonsRowDoc;
- Gtk::VBox _editDocV;
-
- Gtk::Notebook _notebook;
-
- SwatchWatcher* rootWatcher;
- std::vector<Inkscape::XML::NodeObserver*> rootWatchers;
-
- std::vector<Inkscape::XML::NodeObserver*> docWatchers;
- SwatchWatcher* docWatcher;
+ static void _trackDocument( SwatchesPanel *panel, SPDocument *document );
+ static void handleDefsModified(SPDocument *document);
+
+ PreviewHolder* _holder;
+ ColorItem* _clear;
+ ColorItem* _remove;
+ int _currentIndex;
SPDesktop* _currentDesktop;
SPDocument* _currentDocument;
-
- bool _dnd_into;
- SPObject* _dnd_source;
- SPObject* _dnd_target;
sigc::connection _documentConnection;
sigc::connection _selChanged;
+
+ friend class DocTrack;
};
} //namespace Dialogs
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 2eba8bb8c..361a54a90 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -358,7 +358,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
{
using Inkscape::UI::Dialogs::SwatchesPanel;
- dtw->panels = new SwatchesPanel("/embedded/swatches", false);
+ dtw->panels = new SwatchesPanel("/embedded/swatches" /*false*/);
dtw->panels->setOrientation(SP_ANCHOR_SOUTH);
#if GTK_CHECK_VERSION(3,0,0)