/* * Tabular.c -- Implementation of Tabular item. * * Authors : Patrick Lecoanet. * Creation date : * * $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 "tkZinc.h" #include #include static const char rcsid[] = "$Id$"; static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $"; /* ********************************************************************************** * * Specific Tabular item record * ********************************************************************************** */ typedef struct _TabularItemStruct { ItemStruct header; /* Public data */ ZnPoint pos; ZnAnchor anchor; ZnAnchor connection_anchor; /* Private data */ FieldSetStruct field_set; } TabularItemStruct, *TabularItem; static ZnAttrConfig tabular_attrs[] = { { ZN_CONFIG_ANCHOR, "-anchor", NULL, Tk_Offset(TabularItemStruct, anchor), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_BOOL, "-composerotation", NULL, Tk_Offset(TabularItemStruct, header.flags), COMPOSE_ROTATION_BIT, ZN_COORDS_FLAG, False }, { ZN_CONFIG_BOOL, "-composescale", NULL, Tk_Offset(TabularItemStruct, header.flags), COMPOSE_SCALE_BIT, ZN_COORDS_FLAG, False }, { ZN_CONFIG_ITEM, "-connecteditem", NULL, Tk_Offset(TabularItemStruct, header.connected_item), 0, ZN_COORDS_FLAG|ZN_ITEM_FLAG, False }, { ZN_CONFIG_ANCHOR, "-connectionanchor", NULL, Tk_Offset(TabularItemStruct, connection_anchor), 0, ZN_COORDS_FLAG, False }, { ZN_CONFIG_LABEL_FORMAT, "-labelformat", NULL, Tk_Offset(TabularItemStruct, field_set.label_format), 0, ZN_COORDS_FLAG|ZN_CLFC_FLAG, False }, { ZN_CONFIG_UINT, "-numfields", NULL, Tk_Offset(TabularItemStruct, field_set.num_fields), 0, 0, True }, { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(TabularItemStruct, pos), 0, ZN_COORDS_FLAG, False}, { ZN_CONFIG_PRI, "-priority", NULL, Tk_Offset(TabularItemStruct, header.priority), 0, ZN_DRAW_FLAG|ZN_REPICK_FLAG, False }, { ZN_CONFIG_BOOL, "-sensitive", NULL, Tk_Offset(TabularItemStruct, header.flags), SENSITIVE_BIT, ZN_REPICK_FLAG, False }, { ZN_CONFIG_TAGS, "-tags", NULL, Tk_Offset(TabularItemStruct, header.tags), 0, 0, False }, { ZN_CONFIG_BOOL, "-visible", NULL, Tk_Offset(TabularItemStruct, 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[]) { WidgetInfo *wi = item->wi; TabularItem tab = (TabularItem) item; FieldSet field_set = &tab->field_set; item->priority = DEFAULT_TABULAR_PRIORITY; SET(item->flags, VISIBLE_BIT); SET(item->flags, SENSITIVE_BIT); SET(item->flags, COMPOSE_SCALE_BIT); SET(item->flags, COMPOSE_ROTATION_BIT); tab->anchor = ZnAnchorNW; tab->connection_anchor = ZnAnchorSW; tab->pos.x = tab->pos.y = 0.0; field_set->wi = wi; field_set->label_format = NULL; /* * Then try to see if some fields are needed. */ if ((*argc > 0) && (Tcl_GetString((*args)[0])[0] != '-') && (Tcl_GetIntFromObj(wi->interp, (*args)[0], &field_set->num_fields) != ZN_ERROR)) { *args += 1; *argc -= 1; ITEM_P.InitFields(field_set); } else { Tcl_AppendResult(wi->interp, " number of fields expected", NULL); return ZN_ERROR; } item->part_sensitive = 0; return ZN_OK; } /* ********************************************************************************** * * Clone -- * ********************************************************************************** */ static void Clone(Item item) { ITEM_P.CloneFields(&((TabularItem) item)->field_set); } /* ********************************************************************************** * * Destroy -- * ********************************************************************************** */ static void Destroy(Item item) { ITEM_P.FreeFields(&((TabularItem) item)->field_set); } /* ********************************************************************************** * * Configure -- * ********************************************************************************** */ static int Configure(Item item, int argc, Tcl_Obj *CONST argv[], int *flags) { Item old_connected; old_connected = item->connected_item; if (ITEM_P.ConfigureAttributes((char *) item, -1, argc, argv, flags) == ZN_ERROR) { return ZN_ERROR; } if (ISSET(*flags, ZN_ITEM_FLAG)) { /* * If the new connected item is not appropriate back up * to the old one. */ if ((item->connected_item == ZN_NO_ITEM) || (item->connected_item->class->has_anchors && (item->parent == item->connected_item->parent))) { ITEM.UpdateItemDependency(item, old_connected); } else { item->connected_item = old_connected; } } 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) { TabularItem tab = (TabularItem) item; WidgetInfo *wi = item->wi; FieldSet field_set = &tab->field_set; ZnDim width, height; ResetBBox(&item->item_bounding_box); if (field_set->label_format) { ITEM_P.GetLabelBBox(field_set, &width, &height); /* * The connected item support anchors, this is checked by * configure. */ if (item->connected_item != ZN_NO_ITEM) { item->connected_item->class->GetAnchor(item->connected_item, tab->connection_anchor, &field_set->label_pos); } else { ZnTransformPoint(wi->current_transfo, &tab->pos, &field_set->label_pos); } Anchor2Origin(&field_set->label_pos, width, height, tab->anchor, &field_set->label_pos); /* * Setup the item bounding box. */ item->item_bounding_box.orig = field_set->label_pos; item->item_bounding_box.corner.x = field_set->label_pos.x + width; item->item_bounding_box.corner.y = field_set->label_pos.y + height; /* * Update connected items. */ SET(item->flags, UPDATE_DEPENDENT_BIT); } } /* ********************************************************************************** * * 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 ITEM_P.FieldsToArea(&((TabularItem) item)->field_set, area); } /* ********************************************************************************** * * Draw -- * ********************************************************************************** */ static void Draw(Item item) { ITEM_P.DrawFields(&((TabularItem) item)->field_set); } /* ********************************************************************************** * * Render -- * ********************************************************************************** */ static void Render(Item item) { ITEM_P.RenderFields(&((TabularItem) item)->field_set); } /* ********************************************************************************** * * IsSensitive -- * ********************************************************************************** */ static ZnBool IsSensitive(Item item, int item_part) { if (ISCLEAR(item->flags, SENSITIVE_BIT) || !item->parent->class->IsSensitive(item->parent, ZN_NO_PART)) { return False; } return ITEM_P.IsFieldSensitive(&((TabularItem) item)->field_set, item_part); } /* ********************************************************************************** * * Pick -- * We tell what our label tells. * ********************************************************************************** */ static double Pick(Item item, ZnPoint *p, Item start_item, int aperture, Item *a_item, int *part) { int best_part; double dist; dist = ITEM_P.FieldsPick(&((TabularItem) item)->field_set, p, &best_part); /* printf("tabular %d reporting part %d, distance %lf\n", item->id, best_part, dist); */ *part = best_part; return dist; } /* ********************************************************************************** * * PostScript -- * ********************************************************************************** */ static void PostScript(Item item, PostScriptInfo ps_info) { } /* ********************************************************************************** * * GetFieldSet -- * ********************************************************************************** */ static FieldSet GetFieldSet(Item item) { return &((TabularItem) item)->field_set; } /* ********************************************************************************** * * GetAnchor -- * ********************************************************************************** */ static void GetAnchor(Item item, ZnAnchor anchor, ZnPoint *p) { FieldSet field_set = &((TabularItem) item)->field_set; ZnDim width, height; if (field_set->label_format) { ITEM_P.GetLabelBBox(field_set, &width, &height); Origin2Anchor(&field_set->label_pos, width, height, anchor, p); } else { p->x = p->y = 0.0; } } /* ********************************************************************************** * * GetClipVertices -- * Get the clipping shape. * ********************************************************************************** */ static ZnBool GetClipVertices(Item item, ZnPoly *poly) { FieldSet field_set = &((TabularItem) item)->field_set; ZnDim width, height; ZnPoint *points; poly->num_contours = 0; if (field_set->label_format) { ITEM_P.GetLabelBBox(field_set, &width, &height); ZnListAssertSize(item->wi->work_pts, 2); points = (ZnPoint *) ZnListArray(item->wi->work_pts); POLY_CONTOUR1(poly, points, 2); points[0] = field_set->label_pos; points[1].x = points[0].x + width; points[1].y = points[0].y + height; } return True; } /* ********************************************************************************** * * Coords -- * Return or edit the item origin. This doesn't take care of * the possible attachment. The change will be effective at the * end of the attachment. * ********************************************************************************** */ static int Coords(Item item, int contour, int index, int cmd, ZnPoint **pts, int *num_pts) { TabularItem tabular = (TabularItem) item; if ((cmd == COORDS_ADD) || (cmd == COORDS_ADD_LAST) || (cmd == COORDS_REMOVE)) { Tcl_AppendResult(item->wi->interp, " tabulars 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 tabulars", NULL); return ZN_ERROR; } tabular->pos = (*pts)[0]; ITEM.Invalidate(item, ZN_COORDS_FLAG); } else if ((cmd == COORDS_READ) || (cmd == COORDS_READ_ALL)) { *num_pts = 1; *pts = &tabular->pos; } return ZN_OK; } /* ********************************************************************************** * * Part -- * Convert a private part from/to symbolic representation. * ********************************************************************************** */ static int Part(Item item, Tcl_Obj **part_spec, int *part) { char *part_str; char *end; if (*part_spec) { part_str = Tcl_GetString(*part_spec); if (strlen(part_str) == 0) { *part = ZN_NO_PART; } else if (isdigit(part_str[0])) { *part = strtol(part_str, &end, 0); if ((*end != 0) || (*part < 0) || (*part >= ((TabularItem) item)->field_set.num_fields)) { goto part_error; } } else { part_error: Tcl_AppendResult(item->wi->interp, " invalid item part specification", NULL); return ZN_ERROR; } } else { if (*part >= 0) { *part_spec = Tcl_NewIntObj(*part); } else { *part_spec = NewStringObj(""); } } return ZN_OK; } /* ********************************************************************************** * * Exported functions structs -- * ********************************************************************************** */ static ItemClassStruct TABULAR_ITEM_CLASS = { sizeof(TabularItemStruct), True, /* has_fields */ 0, /* num_parts */ True, /* has_anchors */ "tabular", tabular_attrs, Init, Clone, Destroy, Configure, Query, GetFieldSet, GetAnchor, GetClipVertices, Coords, NULL, /* InsertChars */ NULL, /* DeleteChars */ NULL, /* Cursor */ NULL, /* Index */ Part, NULL, /* Selection */ NULL, /* Contour */ ComputeCoordinates, ToArea, Draw, Render, IsSensitive, Pick, NULL, /* PickVertex */ PostScript }; ZnItemClassId ZnTabular = (ZnItemClassId) &TABULAR_ITEM_CLASS;