diff options
-rw-r--r-- | generic/tkZinc.c | 191 |
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); |