aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--generic/tkZinc.c191
1 files changed, 103 insertions, 88 deletions
diff --git a/generic/tkZinc.c b/generic/tkZinc.c
index 23c4b47..0b4c53a 100644
--- a/generic/tkZinc.c
+++ b/generic/tkZinc.c
@@ -2531,15 +2531,17 @@ FindItems(ZnWInfo *wi,
if (result == TCL_ERROR) {
return TCL_ERROR;
}
- item = item->parent;
- if (argc == first+3) {
- uid = Tk_GetUid(Tcl_GetString(args[first+2]));
- }
- while (item != ZN_NO_ITEM) {
- if (!uid || ZnITEM.HasTag(item, uid)) {
- ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
- }
+ if (item) {
item = item->parent;
+ if (argc == first+3) {
+ uid = Tk_GetUid(Tcl_GetString(args[first+2]));
+ }
+ while (item != ZN_NO_ITEM) {
+ if (!uid || ZnITEM.HasTag(item, uid)) {
+ ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
+ }
+ item = item->parent;
+ }
}
}
break;
@@ -2994,6 +2996,9 @@ Contour(ZnWInfo *wi,
&controls, &num_points, NULL) == TCL_ERROR) {
return TCL_ERROR;
}
+ /*
+ * Processing contours from an explicit list.
+ */
ZnPolyContour1(&poly, NULL, num_points, False);
/*
* Allocate a fresh point array, ZnParseCoordList returns a shared
@@ -3024,6 +3029,9 @@ Contour(ZnWInfo *wi,
poly.contours[0].controls = controls;
}
else {
+ /*
+ * Processing contours from an item
+ */
if (winding_flag == 0) {
Tcl_AppendResult(wi->interp,
"Must supply an explicit winding direction (-1, 1)\nwhen adding a contour from an item",
@@ -3037,7 +3045,6 @@ Contour(ZnWInfo *wi,
Update(wi);
if (!shape->class->GetContours &&
!shape->class->GetClipVertices) {
- noshape:
Tcl_AppendResult(wi->interp, "class: \"", shape->class->name,
"\" can't give a polygonal shape", NULL);
return TCL_ERROR;
@@ -3050,11 +3057,15 @@ Contour(ZnWInfo *wi,
* shapes (i.e tose returning a bounding box).
*/
tristrip.num_strips = 0;
+ /*
+ * GetClipVertices _may_ return a tristrip describing a fan
+ * this would lead to strange results. For now, this case
+ * should not appear, the items candidates to such a behavior
+ * export a GetContours method which has higher precedence.
+ */
simple = shape->class->GetClipVertices(shape, &tristrip);
- if (!simple) {
- goto noshape;
- }
- ZnPolyContour1(&poly, tristrip.strip1.points, tristrip.strip1.num_points, False);
+ ZnPolyContour1(&poly, tristrip.strip1.points, tristrip.strip1.num_points,
+ False);
poly.contours[0].controls = NULL;
}
else {
@@ -3098,7 +3109,7 @@ Contour(ZnWInfo *wi,
poly.contours[0].controls = NULL;
}
else {
- /* Unshare the contour array */
+ /* Unshare the contour array or use the static storage */
contours = poly.contours;
if (poly.num_contours == 1) {
poly.contours = &poly.contour1;
@@ -3123,20 +3134,21 @@ Contour(ZnWInfo *wi,
* Unshare the point array.
*/
poly.contours[i].points = ZnMalloc(num_points*sizeof(ZnPoint));
-
- if (((poly.num_contours == 1) && ((winding_flag == -1) ^ cw)) ||
- ((poly.num_contours > 1) && (winding_flag == -1))) {
+ ZnTransformPoints(&inv, points, poly.contours[i].points, num_points);
+
+ if ((((poly.num_contours == 1) && ((winding_flag == -1) ^ cw)) ||
+ ((poly.num_contours > 1) && (winding_flag == -1)))) {
ZnPoint p;
-
- /* Revert and transform the coords */
+
+ revert = True;
+ /* Revert the points */
poly.contours[i].cw = ! cw;
for (j = 0, k = num_points-1; j < k; j++, k--) {
- p = points[j];
- points[j] = points[k];
- points[k] = p;
+ p = poly.contours[i].points[j];
+ poly.contours[i].points[j] = poly.contours[i].points[k];
+ poly.contours[i].points[k] = p;
}
- ZnTransformPoints(&inv, points, poly.contours[i].points, num_points);
-
+
/* Revert the controls */
if (contours[i].controls) {
for (j = 0; j < num_points; j++) {
@@ -3145,7 +3157,6 @@ Contour(ZnWInfo *wi,
}
}
else {
- ZnTransformPoints(&inv, points, poly.contours[i].points, num_points);
if (contours[i].controls) {
memcpy(poly.contours[i].controls, contours[i].controls, num_points);
}
@@ -5943,7 +5954,12 @@ Event(ClientData client_data, /* Information about widget. */
*/
static void
DoEvent(ZnWInfo *wi,
- XEvent *event)
+ XEvent *event,
+ ZnBool bind_item, /* Controls whether item bindings will trigger.
+ * Useful for Enter/Leaves between fields */
+ ZnBool bind_part) /* Controls whether part bindings will trigger.
+ * Useful for precise control of Enter/Leaves
+ * during grabs. */
{
#define NUM_STATIC 4
ClientData items[NUM_STATIC], *its;
@@ -5953,7 +5969,6 @@ DoEvent(ZnWInfo *wi,
ClientData *tag_list = NULL;
ZnItem item;
int part;
- ZnBool bind_part, bind_item;
#define BIND_ITEM(test) \
if (bind_item && (test)) { \
@@ -5992,19 +6007,12 @@ DoEvent(ZnWInfo *wi,
num = 0;
num_tags = 0;
its = items;
- bind_part = ((wi->current_part != ZN_NO_PART) &&
+ bind_part = (bind_part &&
+ (wi->current_part != ZN_NO_PART) &&
item->class->IsSensitive(item, part) &&
(wi->current_item->class->num_parts ||
wi->current_item->class->GetFieldSet));
- /*
- * This is needed to avoid generating enter and leave
- * event on items when crossing a field boundary inside
- * the item. If not bind_item we do not want to trigger
- * any binding related to the item only those pertaining
- * to the fields.
- */
- bind_item = (((event->type != EnterNotify) && (event->type != LeaveNotify)) ||
- (wi->current_item != wi->new_item));
+
/*printf("type=%s, current=%d, new=%d --> %s, currentp %d, newp %d\n",
event->type==EnterNotify?"<Enter>":
event->type==LeaveNotify?"<Leave>":
@@ -6103,10 +6111,16 @@ DoEvent(ZnWInfo *wi,
*/
static void
PickCurrentItem(ZnWInfo *wi,
- XEvent *event)
+ XEvent *event)
{
- int button_down;
+ int button_down;
+ ZnItem item;
+ ZnBool back_inside = False;
+ ZnBool grab_release = False;
+ /*printf("PickCurrent current=%d, new=%d\n",
+ wi->current_item?wi->current_item->id:0,
+ wi->new_item?wi->new_item->id:0);*/
/*
* Check whether or not a button is down. If so, we'll log entry
* and exit into and out of the current item, but not entry into
@@ -6116,7 +6130,8 @@ PickCurrentItem(ZnWInfo *wi,
button_down = wi->state
& (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask);
if (!button_down) {
- wi->flags &= ~ZN_LEFT_GRABBED_ITEM;
+ CLEAR(wi->flags, ZN_GRABBED_ITEM);
+ CLEAR(wi->flags, ZN_GRABBED_PART);
}
/*
@@ -6161,7 +6176,7 @@ PickCurrentItem(ZnWInfo *wi,
* Leave event handler for the old current item) then just return;
* the pending call will do everything that's needed.
*/
- if (wi->flags & ZN_REPICK_IN_PROGRESS) {
+ if (ISSET(wi->flags, ZN_REPICK_IN_PROGRESS)) {
fprintf(stderr, "PickCurrentItem recursive\n");
return;
}
@@ -6170,11 +6185,12 @@ PickCurrentItem(ZnWInfo *wi,
* A LeaveNotify event automatically means that there's no current
* object, so the check for closest item can be skipped.
*/
+ item = wi->new_item;
if (wi->pick_event.type != LeaveNotify) {
ZnPickStruct ps;
ZnReal dist;
ZnPoint p;
-
+
p.x = wi->pick_event.xcrossing.x;
p.y = wi->pick_event.xcrossing.y;
ps.point = &p;
@@ -6196,30 +6212,36 @@ PickCurrentItem(ZnWInfo *wi,
wi->new_item = ZN_NO_ITEM;
wi->new_part = ZN_NO_PART;
}
+ /*
+ * This state is needed to do a valid detection
+ * of Enter during a grab.
+ */
+ back_inside = (wi->new_item != item);
/*printf("------ PickCurrentItem current: %d %d, new %d %d\n",
wi->current_item==ZN_NO_ITEM?0:wi->current_item->id, wi->current_part,
wi->new_item==ZN_NO_ITEM?0:wi->new_item->id, wi->new_part);*/
- if ((wi->new_item == wi->current_item) && (wi->new_part == wi->current_part) &&
- !(wi->flags & ZN_LEFT_GRABBED_ITEM)) {
+ if ((wi->new_item == wi->current_item) &&
+ (wi->new_part == wi->current_part) &&
+ ISCLEAR(wi->flags, ZN_GRABBED_ITEM) &&
+ ISCLEAR(wi->flags, ZN_GRABBED_PART)) {
/*
- * Nothing to do: the current item/part hasn't changed.
+ * Nothing to do: the current item/part hasn't changed.
*/
return;
}
-
+
/*
- * Simulate a LeaveNotify event on the previous current item and
- * an EnterNotify event on the new current item. Remove the "current"
- * tag from the previous current item and place it on the new current
- * item.
+ * Simulate a LeaveNotify event on the previous current item.
+ * Remove the "current" tag from the previous current item.
*/
- if (((wi->new_item != wi->current_item) || (wi->new_part != wi->current_part)) &&
- (wi->current_item != ZN_NO_ITEM) && !(wi->flags & ZN_LEFT_GRABBED_ITEM)) {
+ if ((wi->current_item != ZN_NO_ITEM) &&
+ (((wi->new_item != wi->current_item) && ISCLEAR(wi->flags, ZN_GRABBED_ITEM)) ||
+ ((wi->new_part != wi->current_part) && ISCLEAR(wi->flags, ZN_GRABBED_PART)))) {
XEvent event;
- ZnItem item = wi->current_item;
-
+
+ item = wi->current_item;
event = wi->pick_event;
event.type = LeaveNotify;
@@ -6230,9 +6252,10 @@ PickCurrentItem(ZnWInfo *wi,
* always use NotifyAncestor.
*/
event.xcrossing.detail = NotifyAncestor;
- wi->flags |= ZN_REPICK_IN_PROGRESS;
- DoEvent(wi, &event);
- wi->flags &= ~ZN_REPICK_IN_PROGRESS;
+ SET(wi->flags, ZN_REPICK_IN_PROGRESS);
+ DoEvent(wi, &event,
+ wi->new_item != wi->current_item, ISCLEAR(wi->flags, ZN_GRABBED_PART));
+ CLEAR(wi->flags, ZN_REPICK_IN_PROGRESS);
/*
* The check on item below is needed because there could be an
@@ -6248,40 +6271,31 @@ PickCurrentItem(ZnWInfo *wi,
* item was deleted.
*/
}
- if (((wi->new_item != wi->current_item) ||
- (wi->new_part != wi->current_part)) && button_down) {
- wi->flags |= ZN_LEFT_GRABBED_ITEM;
- return;
- }
/*
* Special note: it's possible that wi->new_item == wi->current_item
- * here. This can happen, for example, if ZN_LEFT_GRABBED_ITEM was set or
+ * here. This can happen, for example, if a grab was set or
* if there is only a change in the part number.
*/
- wi->flags &= ~ZN_LEFT_GRABBED_ITEM;
-
- /*
- * Tentative pour éviter d'enlever puis de remettre
- * le tag current sur le même item en ces de changement
- * de partie. Ca marche pas pour l'instant.
- if (wi->current_item != wi->new_item) {
- if (wi->current_item != ZN_NO_ITEM) {
- printf("vvv Removing 'current' from %d\n", wi->current_item->id);
- ZnITEM.RemoveTag(wi->current_item, current_uid);
- }
- }*/
- {
- ZnItem it = wi->current_item;
-
+ if ((wi->new_item != wi->current_item) && button_down) {
+ SET(wi->flags, ZN_GRABBED_ITEM);
+ }
+ else {
+ grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM);
+ CLEAR(wi->flags, ZN_GRABBED_ITEM);
wi->current_item = wi->new_item;
+ }
+ if ((wi->new_part != wi->current_part) && button_down) {
+ SET(wi->flags, ZN_GRABBED_PART);
+ }
+ else {
+ CLEAR(wi->flags, ZN_GRABBED_PART);
wi->current_part = wi->new_part;
- /*
- * Added to enable DoEvent to make a special case for enter/leaves
- * between fields in the same item. It may interact with
- * ZN_LEFT_GRABBED_ITEM.
- */
- wi->new_item = it;
+ }
+
+ if (!grab_release &&
+ (ISSET(wi->flags, ZN_GRABBED_PART) || ISSET(wi->flags, ZN_GRABBED_ITEM))) {
+ return;
}
if (wi->current_item != ZN_NO_ITEM) {
@@ -6298,7 +6312,8 @@ PickCurrentItem(ZnWInfo *wi,
event = wi->pick_event;
event.type = EnterNotify;
event.xcrossing.detail = NotifyAncestor;
- DoEvent(wi, &event);
+ DoEvent(wi, &event,
+ back_inside, !(grab_release && ISSET(wi->flags, ZN_GRABBED_PART)));
}
}
@@ -6380,7 +6395,7 @@ Bind(ClientData client_data, /* Information about widget. */
PickCurrentItem(wi, event);
wi->state ^= mask;
if (wi->current_item != ZN_NO_ITEM) {
- DoEvent(wi, event);
+ DoEvent(wi, event, True, True);
}
}
else {
@@ -6390,7 +6405,7 @@ Bind(ClientData client_data, /* Information about widget. */
* item under the assumption that the button is no longer down.
*/
wi->state = event->xbutton.state;
- DoEvent(wi, event);
+ DoEvent(wi, event, True, True);
event->xbutton.state ^= mask;
wi->state = event->xbutton.state;
PickCurrentItem(wi, event);
@@ -6428,7 +6443,7 @@ Bind(ClientData client_data, /* Information about widget. */
PickCurrentItem(wi, event);
}
- DoEvent(wi, event);
+ DoEvent(wi, event, True, True);
done:
Tcl_Release((ClientData) wi);