/* * Reticle.c -- Implementation of Reticle item. * * Authors : Patrick Lecoanet. * Creation date : Mon Feb 1 12:13:24 1999 * * $Id$ */ /* * Copyright (c) 1993 - 1999 CENA, Patrick Lecoanet -- * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this code; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "Types.h" #include "WidgetInfo.h" #include "Item.h" #include "Geo.h" #include "Draw.h" #define /* void */ SQUARE(/* int */ x) ((x) * (x)) static const char rcsid[] = "$Id$"; static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $"; /* ********************************************************************************** * * Specific Reticle item record * ********************************************************************************** */ typedef struct _ReticleItemStruct { ItemStruct header; /* Public data */ ZnPoint pos; /* Origin world coordinates */ ZnColor line_color; /* circle color */ ZnColor bright_line_color; /* intermediate circle color */ int first_radius; /* first world radius */ int step_size; /* step world size */ int period; /* bright circle period */ int num_circles; /* num cercles max */ LineStyle line_style; /* circles lines styles */ LineStyle bright_line_style; /* Private data */ ZnPoint dev; /* item device coordinate */ ZnDim first_radius_dev; /* first device radius */ ZnDim step_size_dev; /* steps device size */ } ReticleItemStruct, *ReticleItem; static ZnAttrConfig reticle_attrs[] = { { ZN_CONFIG_COLOR, "-brightlinecolor", NULL, Tk_Offset(ReticleItemStruct, bright_line_color), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_LINE_STYLE, "-brightlinestyle", NULL, Tk_Offset(ReticleItemStruct, bright_line_style), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_BOOL, "-composerotation", NULL, Tk_Offset(ReticleItemStruct, header.flags), COMPOSE_ROTATION_BIT, ZN_COORDS_FLAG, False }, { ZN_CONFIG_BOOL, "-composescale", NULL, Tk_Offset(ReticleItemStruct, header.flags), COMPOSE_SCALE_BIT, ZN_COORDS_FLAG, False }, { ZN_CONFIG_DIM, "-stepsize", NULL, Tk_Offset(ReticleItemStruct, step_size), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_DIM, "-firstradius", NULL, Tk_Offset(ReticleItemStruct, first_radius), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_COLOR, "-linecolor", NULL, Tk_Offset(ReticleItemStruct, line_color), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL, Tk_Offset(ReticleItemStruct, line_style), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_UINT, "-numcircles", NULL, Tk_Offset(ReticleItemStruct, num_circles), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_UINT, "-period", NULL, Tk_Offset(ReticleItemStruct, period), 0, ZN_DRAW_FLAG, False }, { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(ReticleItemStruct, pos), 0, ZN_COORDS_FLAG, False}, { ZN_CONFIG_PRI, "-priority", NULL, Tk_Offset(ReticleItemStruct, header.priority), 0, ZN_DRAW_FLAG|ZN_REPICK_FLAG, False }, { ZN_CONFIG_BOOL, "-sensitive", NULL, Tk_Offset(ReticleItemStruct, header.flags), SENSITIVE_BIT, ZN_REPICK_FLAG, False }, { ZN_CONFIG_TAGS, "-tags", NULL, Tk_Offset(ReticleItemStruct, header.tags), 0, 0, False }, { ZN_CONFIG_BOOL, "-visible", NULL, Tk_Offset(ReticleItemStruct, header.flags), VISIBLE_BIT, ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False }, { ZN_CONFIG_END, NULL, NULL, 0, 0, 0 } }; /* ********************************************************************************** * * Init -- * ********************************************************************************** */ static int Init(Item item, int *argc, Tcl_Obj *CONST *args[]) { ReticleItem reticle = (ReticleItem) item; WidgetInfo *wi = item->wi; SET(item->flags, VISIBLE_BIT); CLEAR(item->flags, SENSITIVE_BIT); SET(item->flags, COMPOSE_ROTATION_BIT); SET(item->flags, COMPOSE_SCALE_BIT); item->priority = DEFAULT_RETICLE_PRIORITY; item->part_sensitive = 0; reticle->line_color = ZnGetColorByValue(wi->win, wi->fore_color); reticle->bright_line_color = ZnGetColorByValue(wi->win, wi->fore_color); reticle->first_radius = DEFAULT_RETICLE_STEP_SIZE; reticle->step_size = DEFAULT_RETICLE_STEP_SIZE; reticle->period = DEFAULT_RETICLE_PERIOD; reticle->num_circles = ZN_ANY_CIRCLES; reticle->line_style = LINE_SIMPLE; reticle->bright_line_style = LINE_SIMPLE; reticle->pos.x = 0; reticle->pos.y = 0; reticle->dev.x = 0; reticle->dev.y = 0; reticle->first_radius_dev = 0; reticle->step_size_dev = 0; return ZN_OK; } /* ********************************************************************************** * * Clone -- * ********************************************************************************** */ static void Clone(Item item) { WidgetInfo *wi = item->wi; ReticleItem reticle = (ReticleItem) item; reticle->line_color = ZnGetColorByValue(wi->win, reticle->line_color); reticle->bright_line_color = ZnGetColorByValue(wi->win, reticle->bright_line_color); } /* ********************************************************************************** * * Destroy -- * ********************************************************************************** */ static void Destroy(Item item) { ReticleItem reticle = (ReticleItem) item; ZnFreeColor(reticle->line_color); ZnFreeColor(reticle->bright_line_color); } /* ********************************************************************************** * * Configure -- * ********************************************************************************** */ static int Configure(Item item, int argc, Tcl_Obj *CONST argv[], int *flags) { if (ITEM_P.ConfigureAttributes((char *)item, -1, argc, argv, flags) == ZN_ERROR) { return ZN_ERROR; } return ZN_OK; } /* ********************************************************************************** * * Query -- * ********************************************************************************** */ static int Query(Item item, int argc, Tcl_Obj *CONST argv[]) { if (ITEM_P.QueryAttribute((char *) item, -1, argv[0]) == ZN_ERROR) { return ZN_ERROR; } return ZN_OK; } /* ********************************************************************************** * * ComputeCoordinates -- * ********************************************************************************** */ static void ComputeCoordinates(Item item, ZnBool force) { WidgetInfo *wi = item->wi; ReticleItem reticle = (ReticleItem) item; ZnDim half_width; ZnPoint p, xp; /* Compute center device coordinates */ ZnTransformPoint(wi->current_transfo, &reticle->pos, &reticle->dev); p.x = reticle->pos.x + reticle->step_size; p.y = 0; ZnTransformPoint(wi->current_transfo, &p, &xp); reticle->step_size_dev = xp.x - reticle->dev.x; p.x = reticle->pos.x + reticle->first_radius; ZnTransformPoint(wi->current_transfo, &p, &xp); reticle->first_radius_dev = xp.x - reticle->dev.x; /* Reticle bounding box is zn bounding box or depends on num_circles */ if (reticle->num_circles == ZN_ANY_CIRCLES) { item->item_bounding_box.orig.x = 0; item->item_bounding_box.orig.y = 0; item->item_bounding_box.corner.x = wi->width; item->item_bounding_box.corner.y = wi->height; } else { half_width = reticle->first_radius_dev + (reticle->num_circles - 1) * reticle->step_size_dev; item->item_bounding_box.orig.x = reticle->dev.x - half_width; item->item_bounding_box.orig.y = reticle->dev.y - half_width; item->item_bounding_box.corner.x = item->item_bounding_box.orig.y + (2 * half_width); item->item_bounding_box.corner.y = item->item_bounding_box.orig.y + (2 * half_width); } } /* ********************************************************************************** * * ToArea -- * Tell if the object is entirely outside (-1), * entirely inside (1) or in between (0). * ********************************************************************************** */ static int ToArea(Item item, ZnBBox *area, Tk_Uid tag_uid, int enclosed, ZnBool report) { return -1; } /* ********************************************************************************** * * Draw -- * ********************************************************************************** */ static void Draw(Item item) { WidgetInfo *wi = item->wi; ReticleItem reticle = (ReticleItem) item; ZnDim radius = reticle->first_radius_dev; ZnDim radius_max_dev; XGCValues values; unsigned int i; ZnDim l1, l2, l3, l4; /* int count = 0;*/ /* Compute radius max */ l1 = (ZnDim) hypot(wi->damaged_area.orig.x - reticle->dev.x, wi->damaged_area.orig.y - reticle->dev.y); l2 = (ZnDim) hypot(wi->damaged_area.corner.x - reticle->dev.x, wi->damaged_area.orig.y - reticle->dev.y); l3 = (ZnDim) hypot(wi->damaged_area.orig.x - reticle->dev.x, wi->damaged_area.corner.y - reticle->dev.y); l4 = (ZnDim) hypot(wi->damaged_area.corner.x - reticle->dev.x, wi->damaged_area.corner.y - reticle->dev.y); radius_max_dev = MAX(MAX(l1,l2), MAX(l3, l4)); if (reticle->num_circles > 0) { radius_max_dev = MIN(radius_max_dev, reticle->first_radius_dev + (reticle->num_circles - 1) * reticle->step_size_dev); } while (radius <= radius_max_dev) { SetLineStyle(wi->dpy, wi->gc, reticle->line_style); values.foreground = ZnPixel(reticle->line_color); values.line_width = 0; values.fill_style = FillSolid; XChangeGC(wi->dpy, wi->gc, GCForeground | GCLineWidth | GCFillStyle, &values); for (i = 1; (radius <= radius_max_dev && i < reticle->period); i++) { if ((reticle->dev.x >= wi->damaged_area.orig.x - radius) && (reticle->dev.x <= wi->damaged_area.corner.x + radius) && (reticle->dev.y >= wi->damaged_area.orig.y - radius) && (reticle->dev.y <= wi->damaged_area.corner.y + radius)) { XDrawArc(wi->dpy, wi->draw_buffer, wi->gc, reticle->dev.x - (ZnPos) radius, reticle->dev.y - (ZnPos) radius, (ZnPos) radius * 2 - 1, (ZnPos) radius * 2 - 1, 0, 360 * 64); /* count++;*/ } radius += (reticle->step_size_dev); } if ((radius <= radius_max_dev) && (reticle->dev.x >= wi->damaged_area.orig.x - radius) && (reticle->dev.x <= wi->damaged_area.corner.x + radius) && (reticle->dev.y >= wi->damaged_area.orig.y - radius) && (reticle->dev.y <= wi->damaged_area.corner.y + radius)) { SetLineStyle(wi->dpy, wi->gc, reticle->bright_line_style); values.foreground = ZnPixel(reticle->bright_line_color); values.line_width = 0; values.fill_style = FillSolid; XChangeGC(wi->dpy, wi->gc, GCForeground | GCLineWidth | GCFillStyle, &values); XDrawArc(wi->dpy, wi->draw_buffer, wi->gc, reticle->dev.x - (ZnPos) radius, reticle->dev.y - (ZnPos) radius, (ZnPos) radius * 2 - 1, (ZnPos) radius * 2 - 1, 0, 360 * 64); /*count++;*/ } radius += (reticle->step_size_dev); } /*printf("# circles drawn: %d\n", count);*/ } /* ********************************************************************************** * * Render -- * ********************************************************************************** */ static void Render(Item item) { /*WidgetInfo *wi = item->wi; ReticleItem reticle = (ReticleItem) item;*/ } /* ********************************************************************************** * * IsSensitive -- * ********************************************************************************** */ static ZnBool IsSensitive(Item item, int item_part) { return (ISSET(item->flags, SENSITIVE_BIT) && item->parent->class->IsSensitive(item->parent, ZN_NO_PART)); } /* ********************************************************************************** * * Pick -- * Nothing to pick, we are almost transparent. * ********************************************************************************** */ static double Pick(Item item, ZnPoint *p, Item start_item, int aperture, Item *a_item, int *part) { return 1e40; } /* ********************************************************************************** * * Coords -- * Return or edit the item center. * ********************************************************************************** */ static int Coords(Item item, int contour, int index, int cmd, ZnPoint **pts, int *num_pts) { ReticleItem reticle = (ReticleItem) item; if ((cmd == COORDS_ADD) || (cmd == COORDS_ADD_LAST) || (cmd == COORDS_REMOVE)) { Tcl_AppendResult(item->wi->interp, " reticles can't add or remove vertices", NULL); return ZN_ERROR; } else if ((cmd == COORDS_REPLACE) || (cmd == COORDS_REPLACE_ALL)) { if (*num_pts == 0) { Tcl_AppendResult(item->wi->interp, " coords command need 1 point on reticles", NULL); return ZN_ERROR; } reticle->pos = (*pts)[0]; ITEM.Invalidate(item, ZN_COORDS_FLAG); } else if ((cmd == COORDS_READ) || (cmd == COORDS_READ_ALL)) { *num_pts = 1; *pts = &reticle->pos; } return ZN_OK; } /* ********************************************************************************** * * PostScript -- * ********************************************************************************** */ static void PostScript(Item item, PostScriptInfo ps_info) { } /* ********************************************************************************** * * Exported functions struct -- * ********************************************************************************** */ static ItemClassStruct RETICLE_ITEM_CLASS = { sizeof(ReticleItemStruct), False, /* has_fields */ 0, /* num_parts */ False, /* has_anchors */ "reticle", reticle_attrs, Init, Clone, Destroy, Configure, Query, NULL, /* GetFieldSet */ NULL, /* GetAnchor */ NULL, /* GetClipVertices */ Coords, NULL, /* InsertChars */ NULL, /* DeleteChars */ NULL, /* Cursor */ NULL, /* Index */ NULL, /* Part */ NULL, /* Selection */ NULL, /* Contour */ ComputeCoordinates, ToArea, Draw, Render, IsSensitive, Pick, NULL, /* PickVertex */ PostScript }; ZnItemClassId ZnReticle = (ZnItemClassId) &RETICLE_ITEM_CLASS;