diff --git a/src/zmapWindow/items/zmapWindowContainerBlock.c b/src/zmapWindow/items/zmapWindowContainerBlock.c index 09d0afeaf17cbe9c864af2ec87d06f22980563cf..1ad6c880c5f270c1b8ebaae7783e97eee7f94720 100755 --- a/src/zmapWindow/items/zmapWindowContainerBlock.c +++ b/src/zmapWindow/items/zmapWindowContainerBlock.c @@ -27,9 +27,9 @@ * * Exported functions: See XXXXXXXXXXXXX.h * HISTORY: - * Last edited: Jun 10 14:36 2009 (rds) + * Last edited: Jan 22 20:48 2010 (roy) * Created: Mon Jul 30 13:09:33 2007 (rds) - * CVS info: $Id: zmapWindowContainerBlock.c,v 1.6 2009-06-10 14:00:38 rds Exp $ + * CVS info: $Id: zmapWindowContainerBlock.c,v 1.7 2010-01-22 09:17:43 rds Exp $ *------------------------------------------------------------------- */ @@ -49,22 +49,56 @@ static ZMapSeqBitmap get_bitmap_for_key(ZMapWindowContainerBlock block_data, ZMapFeatureBlock block, GQuark key); - +/* There's some functions for managing ZMapWindowMark here... */ +static gboolean maximise_mark_items_cb(ZMapWindowContainerGroup group_updated, + FooCanvasPoints *group_bounds, + ZMapContainerLevelType group_level, + gpointer user_data); +static void mark_items_create(ZMapWindowContainerBlock container_block, + GdkColor *mark_colour, + GdkBitmap *mark_stipple); +static void mark_items_update_colour(ZMapWindowContainerBlock container_block, + GdkColor *mark_colour, + GdkBitmap *mark_stipple); +static void mark_items_show(ZMapWindowContainerBlock container_block); +static void mark_items_hide(ZMapWindowContainerBlock container_block); + +static gboolean mark_intersects_block(ZMapWindowMark mark, FooCanvasPoints *block_points, + double *mark_world_y1_out, double *mark_world_y2_out); +static gboolean mark_block_update_hook(ZMapWindowContainerGroup group_in_update, + FooCanvasPoints *group_points, + ZMapContainerLevelType group_level, + gpointer user_data); +static gboolean areas_intersection(FooCanvasPoints *area_1, + FooCanvasPoints *area_2, + FooCanvasPoints *intersect); +static gboolean areas_intersect_gt_threshold(FooCanvasPoints *area_1, + FooCanvasPoints *area_2, + double threshold); + +/* All the basic object functions */ static void zmap_window_container_block_class_init (ZMapWindowContainerBlockClass block_data_class); static void zmap_window_container_block_init (ZMapWindowContainerBlock block_data); static void zmap_window_container_block_set_property(GObject *gobject, - guint param_id, - const GValue *value, - GParamSpec *pspec); + guint param_id, + const GValue *value, + GParamSpec *pspec); static void zmap_window_container_block_get_property(GObject *gobject, - guint param_id, - GValue *value, - GParamSpec *pspec); + guint param_id, + GValue *value, + GParamSpec *pspec); static void zmap_window_container_block_destroy (GtkObject *gtkobject); +/* A ZMapWindowContainerGroup 'interface' function. */ +static void zmap_window_container_block_post_create (ZMapWindowContainerGroup group); static GObjectClass *parent_class_G = NULL; +/*! + * \brief Get the GType for the ZMapWindowContainerBlock GObjects + * + * \return GType corresponding to the GObject as registered by glib. + */ GType zmapWindowContainerBlockGetType(void) { @@ -94,7 +128,16 @@ GType zmapWindowContainerBlockGetType(void) return group_type; } - +/*! + * \brief Once a new ZMapWindowContainerBlock object has been created, + * various parameters need to be set. This sets all the params. + * + * \param container The container to set everything on. + * \param feature The container needs to know its Block. + * + * \return ZMapWindowContainerBlock that was edited. + */ + ZMapWindowContainerBlock zmapWindowContainerBlockAugment(ZMapWindowContainerBlock container_block, ZMapFeatureBlock feature) { @@ -104,8 +147,19 @@ ZMapWindowContainerBlock zmapWindowContainerBlockAugment(ZMapWindowContainerBloc return container_block; } +/*! + * \brief Add a column that has been 'compressed' by the application. + * + * ZMap allows for the compressing/temporary hiding of columns and we need + * to keep a list of these. + * + * \param container The container. + * \param column The column that has been compressed. + * + * \return nothing + */ void zmapWindowContainerBlockAddCompressedColumn(ZMapWindowContainerBlock block_data, - FooCanvasGroup *container) + FooCanvasGroup *container) { block_data->compressed_cols = g_list_append(block_data->compressed_cols, container) ; @@ -113,6 +167,17 @@ void zmapWindowContainerBlockAddCompressedColumn(ZMapWindowContainerBlock block_ return ; } +/*! + * \brief Remove columns that have been 'compressed' by the application. + * + * ZMap allows for the compressing/temporary hiding of columns and we need + * to keep a list of these. This gives access to the list and effectively + * pops the list from the block. + * + * \param container The container. + * + * \return the list of columns that the block holds as compressed. + */ GList *zmapWindowContainerBlockRemoveCompressedColumns(ZMapWindowContainerBlock block_data) { GList *list = NULL; @@ -123,6 +188,16 @@ GList *zmapWindowContainerBlockRemoveCompressedColumns(ZMapWindowContainerBlock return list; } +/*! + * \brief Add a column that has been 'bumped' by the application. + * + * ZMap allows for the bumping of columns and we need to keep a list of these. + * + * \param container The container. + * \param column The column that has been bumped. + * + * \return nothing + */ void zmapWindowContainerBlockAddBumpedColumn(ZMapWindowContainerBlock block_data, FooCanvasGroup *container) { @@ -135,6 +210,16 @@ void zmapWindowContainerBlockAddBumpedColumn(ZMapWindowContainerBlock block_data return ; } +/*! + * \brief Remove columns that have been 'bumped' by the application. + * + * ZMap allows for the bumping of columns and we need to keep a list of these. + * This gives access to the list and effectively pops the list from the block. + * + * \param container The container. + * + * \return the list of columns that the block holds as bumped. + */ GList *zmapWindowContainerBlockRemoveBumpedColumns(ZMapWindowContainerBlock block_data) { GList *list = NULL; @@ -145,135 +230,113 @@ GList *zmapWindowContainerBlockRemoveBumpedColumns(ZMapWindowContainerBlock bloc return list; } -static gboolean maximise_mark_items_cb(ZMapWindowContainerGroup group_updated, - FooCanvasPoints *group_bounds, - ZMapContainerLevelType group_level, - gpointer user_data) -{ - ZMapWindowContainerBlock container_block = (ZMapWindowContainerBlock)group_updated; - FooCanvasRE *mark_item_rectangle; - gboolean status = TRUE; - - zMapAssert(group_level == ZMAPCONTAINER_LEVEL_BLOCK); - - if(container_block->mark.top_item) - { - mark_item_rectangle = (FooCanvasRE *)container_block->mark.top_item; - - mark_item_rectangle->x1 = group_bounds->coords[0]; - mark_item_rectangle->y1 = group_bounds->coords[1]; - mark_item_rectangle->x2 = group_bounds->coords[2]; - - mark_item_rectangle->y2 = container_block->mark.start; - } - - if(container_block->mark.bottom_item) - { - mark_item_rectangle = (FooCanvasRE *)container_block->mark.bottom_item; - - mark_item_rectangle->x1 = group_bounds->coords[0]; - /* */ - mark_item_rectangle->y1 = container_block->mark.end; - mark_item_rectangle->x2 = group_bounds->coords[2]; - mark_item_rectangle->y2 = group_bounds->coords[3]; - } - - return status; -} - +/*! + * \brief Code to actually mark the Block + * + * The zmapWindowMark code is only a controller for the mark. The setting for + * the items themselves happen here. + * + * \param container_block The container to mark + * \param mark_colour The colour to mark with + * \param mark_stipple The stipple to mark with + * \param start The 'start' of the mark + * \param end The 'end' of the mark + * + * \return nothing. + * */ void zmapWindowContainerBlockMark(ZMapWindowContainerBlock container_block, - GdkColor *mark_colour, - GdkBitmap *mark_stipple, - double start, double end) + ZMapWindowMark mark) { ZMapWindowContainerGroup container; - ZMapWindowContainerOverlay overlay; ZMapWindowContainerBackground background; + GdkColor *mark_colour; + GdkBitmap *mark_stipple; + FooCanvasPoints bounds; + double coords[4]; container = (ZMapWindowContainerGroup)container_block; - if((overlay = zmapWindowContainerGetOverlay(container)) && - (background = zmapWindowContainerGetBackground(container))) + if((background = zmapWindowContainerGetBackground(container))) { - FooCanvasGroup *parent; - double x1, x2, y1, y2; -#ifdef DEBUG_MARK_WITH_OUTLINE - GdkColor outline; - - gdk_color_parse("red", &outline); -#endif /* DEBUG_MARK_WITH_OUTLINE */ - parent = (FooCanvasGroup *)overlay; + mark_colour = zmapWindowMarkGetColour(mark); + mark_stipple = zmapWindowMarkGetStipple(mark); + /* Get the gdk stuff ^^ and then update the colour and stipple. */ + mark_items_update_colour(container_block, mark_colour, mark_stipple); /* We get the current bounds of the background. It will have * been cropped to the scroll region. The UpdateHook takes care * of maximising it. */ - foo_canvas_item_get_bounds((FooCanvasItem *)background, &x1, &y1, &x2, &y2); - - container_block->mark.start = start; - - container_block->mark.top_item = - foo_canvas_item_new(parent, - FOO_TYPE_CANVAS_RECT, -#ifdef DEBUG_MARK_WITH_OUTLINE - "outline_color_gdk", &outline, - "width_pixels", 1, -#endif /* DEBUG_MARK_WITH_OUTLINE */ - "fill_color_gdk", mark_colour, - "fill_stipple", mark_stipple, - "x1", x1, - "x2", x2, - "y1", y1, - "y2", start, - NULL); - - container_block->mark.end = end; - - container_block->mark.bottom_item = - foo_canvas_item_new(parent, - FOO_TYPE_CANVAS_RECT, -#ifdef DEBUG_MARK_WITH_OUTLINE - "outline_color_gdk", &outline, - "width_pixels", 1, -#endif /* DEBUG_MARK_WITH_OUTLINE */ - "fill_color_gdk", mark_colour, - "fill_stipple", mark_stipple, - "x1", x1, - "x2", x2, - "y1", end, - "y2", y2, - NULL); + foo_canvas_item_get_bounds((FooCanvasItem *)background, + &coords[0], &coords[1], + &coords[2], &coords[3]); + + /* If the coords look valid, at least one is > zero, then we can just attempt to + * update the mark items and show them here. + */ + if(coords[0] > 0.0 || coords[1] > 0.0 || coords[2] > 0.0 || coords[3] > 0.0) + { + /* A FooCanvasPoints on the stack, while we update the mark items */ + bounds.coords = &coords[0]; + bounds.num_points = 2; + bounds.ref_count = 1; + /* Call the update hook as if we were in an update cycle. */ + mark_block_update_hook(container, &bounds, ZMAPCONTAINER_LEVEL_BLOCK, mark); + + /* + * This seemed like a good idea, but I don't think it's necessary, so I've commented it. + * It does mean we have to Request Reposition though, which might be time consuming. + * + * maximise_mark_items_cb(container, &bounds, ZMAPCONTAINER_LEVEL_BLOCK, NULL); + */ + } + else + { + /* The coords don't look valid so we'll have to setup an update hook to update + * the mark items next time the update cycle comes around. */ + zmapWindowContainerGroupAddUpdateHook(container, mark_block_update_hook, mark); + } + /* This is required to preserve and crop the mark while zooming. */ zmapWindowContainerGroupAddUpdateHook(container, maximise_mark_items_cb, &(container_block->mark)); + + zmapWindowContainerRequestReposition(container); } return ; } +/*! + * \brief Unmark the block + * + * Reverse of Mark + * + * \param container_block The container to remove the mark from. + * + * \return nothing + * */ void zmapWindowContainerBlockUnmark(ZMapWindowContainerBlock container_block) { ZMapWindowContainerGroup container; - ZMapWindowContainerOverlay overlay; container = (ZMapWindowContainerGroup)container_block; + mark_items_hide(container_block); + zmapWindowContainerGroupRemoveUpdateHook(container, maximise_mark_items_cb, &(container_block->mark)); - container_block->mark.top_item = NULL; - container_block->mark.bottom_item = NULL; + container_block->mark.start = 0.0; container_block->mark.end = 0.0; - if((overlay = zmapWindowContainerGetOverlay(container))) - { - zmapWindowContainerUtilsRemoveAllItems((FooCanvasGroup *)overlay); - } - return ; } -void zmapWindowContainerBlockMarkRegion(ZMapWindowContainerBlock block_data, +/* --- */ + + +void zmapWindowContainerBlockFlagRegion(ZMapWindowContainerBlock block_data, ZMapFeatureBlock block) { ZMapSeqBitmap bitmap; @@ -292,7 +355,7 @@ void zmapWindowContainerBlockMarkRegion(ZMapWindowContainerBlock block_data, return ; } -void zmapWindowContainerBlockMarkRegionForColumn(ZMapWindowContainerBlock container_block, +void zmapWindowContainerBlockFlagRegionForColumn(ZMapWindowContainerBlock container_block, ZMapFeatureBlock block, ZMapWindowContainerFeatureSet container_set) { @@ -315,8 +378,8 @@ void zmapWindowContainerBlockMarkRegionForColumn(ZMapWindowContainerBlock return ; } -GList *zmapWindowContainerBlockFilterMarkedColumns(ZMapWindowContainerBlock block_data, - GList *list, int world1, int world2) +GList *zmapWindowContainerBlockFilterFlaggedColumns(ZMapWindowContainerBlock block_data, + GList *list, int world1, int world2) { GList *key_list; @@ -370,7 +433,9 @@ ZMapWindowContainerBlock zmapWindowContainerBlockDestroy(ZMapWindowContainerBloc } -/* INTERNAL */ +/* + * INTERNAL + */ static ZMapSeqBitmap get_bitmap_for_key(ZMapWindowContainerBlock block_data, ZMapFeatureBlock block, @@ -395,16 +460,366 @@ static ZMapSeqBitmap get_bitmap_for_key(ZMapWindowContainerBlock block_data, return bitmap; } +static gboolean maximise_mark_items_cb(ZMapWindowContainerGroup group_updated, + FooCanvasPoints *group_bounds, + ZMapContainerLevelType group_level, + gpointer user_data) +{ + ZMapWindowContainerBlock container_block = (ZMapWindowContainerBlock)group_updated; + FooCanvasRE *mark_item_rectangle; + gboolean status = TRUE; + + zMapAssert(group_level == ZMAPCONTAINER_LEVEL_BLOCK); + + if(container_block->mark.start > 0.0 && container_block->mark.end > 0.0) + { + if(container_block->mark.top_item) + { + mark_item_rectangle = (FooCanvasRE *)container_block->mark.top_item; + + mark_item_rectangle->x1 = group_bounds->coords[0]; + mark_item_rectangle->y1 = group_bounds->coords[1]; + mark_item_rectangle->x2 = group_bounds->coords[2]; + + mark_item_rectangle->y2 = container_block->mark.start; + } + + if(container_block->mark.bottom_item) + { + mark_item_rectangle = (FooCanvasRE *)container_block->mark.bottom_item; + + mark_item_rectangle->x1 = group_bounds->coords[0]; + /* */ + mark_item_rectangle->y1 = container_block->mark.end; + mark_item_rectangle->x2 = group_bounds->coords[2]; + mark_item_rectangle->y2 = group_bounds->coords[3]; + } + mark_items_show(container_block); + } + else + { + status = FALSE; + } + + return status; +} -/* Object code */ +/* Create the two mark items in the overlay, without a size and we'll update all that later */ +static void mark_items_create(ZMapWindowContainerBlock container_block, + GdkColor *mark_colour, + GdkBitmap *mark_stipple) +{ + ZMapWindowContainerGroup container; + ZMapWindowContainerOverlay overlay; + ZMapWindowContainerBackground background; + + container = (ZMapWindowContainerGroup)container_block; + + if((overlay = zmapWindowContainerGetOverlay(container)) && + (background = zmapWindowContainerGetBackground(container))) + { + FooCanvasGroup *parent; +#ifdef DEBUG_MARK_WITH_OUTLINE + GdkColor outline; + + gdk_color_parse("red", &outline); +#endif /* DEBUG_MARK_WITH_OUTLINE */ + parent = (FooCanvasGroup *)overlay; + + container_block->mark.top_item = + foo_canvas_item_new(parent, + FOO_TYPE_CANVAS_RECT, +#ifdef DEBUG_MARK_WITH_OUTLINE + "outline_color_gdk", &outline, + "width_pixels", 1, +#endif /* DEBUG_MARK_WITH_OUTLINE */ + NULL); + + container_block->mark.bottom_item = + foo_canvas_item_new(parent, + FOO_TYPE_CANVAS_RECT, +#ifdef DEBUG_MARK_WITH_OUTLINE + "outline_color_gdk", &outline, + "width_pixels", 1, +#endif /* DEBUG_MARK_WITH_OUTLINE */ + NULL); + + mark_items_update_colour(container_block, mark_colour, mark_stipple); + } + + return ; +} + + +static void mark_items_update_colour(ZMapWindowContainerBlock container_block, + GdkColor *mark_colour, + GdkBitmap *mark_stipple) +{ + /* If they exist set the fill colour and stipple */ + if(container_block->mark.top_item) + { + foo_canvas_item_set(container_block->mark.top_item, + "fill_color_gdk", mark_colour, + "fill_stipple", mark_stipple, + NULL); + } + + if(container_block->mark.bottom_item) + { + foo_canvas_item_set(container_block->mark.bottom_item, + "fill_color_gdk", mark_colour, + "fill_stipple", mark_stipple, + NULL); + } + + return ; +} + +static void mark_items_show(ZMapWindowContainerBlock container_block) +{ + /* If they exist show them */ + if(container_block->mark.top_item) + foo_canvas_item_show(container_block->mark.top_item); + + if(container_block->mark.bottom_item) + foo_canvas_item_show(container_block->mark.bottom_item); + + return ; +} + +static void mark_items_hide(ZMapWindowContainerBlock container_block) +{ + /* If they exist hide them */ + if(container_block->mark.top_item) + foo_canvas_item_hide(container_block->mark.top_item); + + if(container_block->mark.bottom_item) + foo_canvas_item_hide(container_block->mark.bottom_item); + + return ; +} + + +static gboolean mark_intersects_block(ZMapWindowMark mark, FooCanvasPoints *block_points, + double *mark_world_y1_out, double *mark_world_y2_out) +{ + FooCanvasPoints mark_points; + double mark_coords[4]; + gboolean result = FALSE; + + zmapWindowMarkGetWorldRange(mark, + &mark_coords[0], &mark_coords[1], + &mark_coords[2], &mark_coords[3]); + mark_points.coords = &mark_coords[0]; + mark_points.num_points = 2; + mark_points.ref_count = 1; + + if(mark_coords[0] == 0.0) + mark_coords[0] = block_points->coords[0]; + if(mark_coords[2] == 0.0) + mark_coords[2] = block_points->coords[2]; + + if((result = areas_intersect_gt_threshold(block_points, &mark_points, 0.55))) + { + if(mark_world_y1_out) + *mark_world_y1_out = mark_coords[1]; + if(mark_world_y2_out) + *mark_world_y2_out = mark_coords[3]; + } + + return result; +} + +static gboolean mark_block_update_hook(ZMapWindowContainerGroup group_in_update, + FooCanvasPoints *group_points, + ZMapContainerLevelType group_level, + gpointer user_data) +{ + ZMapWindowContainerBackground background; + ZMapWindowContainerBlock container_block; + ZMapWindowMark mark = (ZMapWindowMark)user_data; + gboolean status = FALSE; + FooCanvasPoints block_points; + double block_coords[4]; + double start, end, dummy_x; + gboolean debug_update_hook = FALSE; + + zMapAssert(group_level == ZMAPCONTAINER_LEVEL_BLOCK); + + block_points.num_points = 2; + block_points.ref_count = 1; + + if((background = zmapWindowContainerGetBackground(group_in_update))) + { + FooCanvasItem *bg_item = FOO_CANVAS_ITEM(background); + + if(debug_update_hook) + { + /* I was concerned that the group_points and the + * item_get_bounds might not marry up, but it appears + * there's no need for concern. */ + foo_canvas_item_get_bounds(bg_item, + &block_coords[0], &block_coords[1], + &block_coords[2], &block_coords[3]); + + if(group_points->coords[0] != block_coords[0] || + group_points->coords[0] != block_coords[0] || + group_points->coords[0] != block_coords[0] || + group_points->coords[0] != block_coords[0]) + { + zMapLogWarning("block %p has item coords: [%f,%f] - [%f,%f]", + group_in_update, + block_coords[0], block_coords[1], + block_coords[2], block_coords[3]); + zMapLogWarning("block %p has grouppoints: [%f,%f] - [%f,%f]\n", + group_in_update, + group_points->coords[0], group_points->coords[1], + group_points->coords[2], group_points->coords[3]); + } + + printf ("block %p has item coords: [%f,%f] - [%f,%f]\n", + group_in_update, + block_coords[0], block_coords[1], + block_coords[2], block_coords[3]); + } + + block_coords[0] = group_points->coords[0]; + block_coords[1] = group_points->coords[1]; + block_coords[2] = group_points->coords[2]; + block_coords[3] = group_points->coords[3]; + + /* We need to compare world coords. coords are item coords */ + /* so we i2w them */ + foo_canvas_item_i2w(bg_item, &block_coords[0], &block_coords[1]); + foo_canvas_item_i2w(bg_item, &block_coords[2], &block_coords[3]); + + if(debug_update_hook) + { + printf ("block %p has wrld coords: [%f,%f] - [%f,%f]\n", + group_in_update, + block_coords[0], block_coords[1], + block_coords[2], block_coords[3]); + } + + block_points.coords = &block_coords[0]; + + start = end = 0.0; + + /* check the intersection */ + if(mark_intersects_block(mark, &block_points, &start, &end)) + { + double world_start, world_end; + + /* Looks like we intersected */ + container_block = (ZMapWindowContainerBlock)group_in_update; + + dummy_x = 0.0; + world_start = start; + world_end = end; + + foo_canvas_item_w2i(bg_item, &dummy_x, &start); + foo_canvas_item_w2i(bg_item, &dummy_x, &end); + + container_block->mark.start = start; + container_block->mark.end = end; + + zmapWindowMarkSetBlockContainer(mark, container_block, start, end, + block_coords[0], world_start, + block_coords[2], world_end); + } + } + + return status; +} + +/* checks whether two areas intersect. + * Only good for a rectangle descibed by 2 points (e.g. x1,y1, x2,y2) */ +static gboolean areas_intersection(FooCanvasPoints *area_1, + FooCanvasPoints *area_2, + FooCanvasPoints *intersect) /* intersect is filled */ +{ + double x1, x2, y1, y2; + gboolean overlap = FALSE; + + x1 = MAX(area_1->coords[0], area_2->coords[0]); + y1 = MAX(area_1->coords[1], area_2->coords[1]); + x2 = MIN(area_1->coords[2], area_2->coords[2]); + y2 = MIN(area_1->coords[3], area_2->coords[3]); + + if(y2 - y1 > 0 && x2 - x1 > 0) + { + intersect->coords[0] = x1; + intersect->coords[1] = y1; + intersect->coords[2] = x2; + intersect->coords[3] = y2; + overlap = TRUE; + } + else + intersect->coords[0] = intersect->coords[1] = + intersect->coords[2] = intersect->coords[3] = 0.0; + + return overlap; +} + + +/* threshold = percentage / 100. i.e. has a range of 0.00000001 -> 1.00000000 */ +/* For 100% overlap pass 1.0, For 50% overlap pass 0.5 */ +static gboolean areas_intersect_gt_threshold(FooCanvasPoints *area_1, + FooCanvasPoints *area_2, + double threshold) +{ + FooCanvasPoints inter; + double inter_coords[4]; + double a1, aI; + gboolean above_threshold = FALSE; + + inter.coords = &inter_coords[0]; + inter.num_points = 2; + inter.ref_count = 1; + + if(areas_intersection(area_1, area_2, &inter)) + { + aI = (inter.coords[2] - inter.coords[0] + 1.0) * (inter.coords[3] - inter.coords[1] + 1.0); + a1 = (area_1->coords[2] - area_1->coords[0] + 1.0) * (area_1->coords[3] - area_1->coords[1] + 1.0); + + if(threshold > 0.0 && threshold < 1.0) + threshold = 1.0 - threshold; + else + threshold = 0.0; /* 100% overlap only */ + + if(inter.coords[0] >= area_1->coords[0] && + inter.coords[1] >= area_1->coords[1] && + inter.coords[2] <= area_1->coords[2] && + inter.coords[3] <= area_1->coords[3]) + { + above_threshold = TRUE; /* completely contained */ + } + else if((aI <= (a1 * (1.0 + threshold))) && (aI >= (a1 * (1.0 - threshold)))) + above_threshold = TRUE; + else + zMapLogWarning("%s", "intersection below threshold"); + } + else + zMapLogWarning("%s", "no intersection"); + + return above_threshold; +} + + + +/* + * OBJECT CODE + */ static void zmap_window_container_block_class_init(ZMapWindowContainerBlockClass block_data_class) { + ZMapWindowContainerGroupClass group_class; GtkObjectClass *gtkobject_class; GObjectClass *gobject_class; - gobject_class = (GObjectClass *)block_data_class; + gobject_class = (GObjectClass *)block_data_class; gtkobject_class = (GtkObjectClass *)block_data_class; + group_class = (ZMapWindowContainerGroupClass)block_data_class; gobject_class->set_property = zmap_window_container_block_set_property; gobject_class->get_property = zmap_window_container_block_get_property; @@ -423,7 +838,9 @@ static void zmap_window_container_block_class_init(ZMapWindowContainerBlockClass #endif - gtkobject_class->destroy = zmap_window_container_block_destroy; + group_class->post_create = zmap_window_container_block_post_create; + + gtkobject_class->destroy = zmap_window_container_block_destroy; return ; } @@ -432,6 +849,7 @@ static void zmap_window_container_block_init(ZMapWindowContainerBlock block_data { block_data->loaded_region_hash = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)zmapSeqBitmapDestroy); block_data->compressed_cols = NULL; + return ; } @@ -452,9 +870,9 @@ static void zmap_window_container_block_set_property(GObject *gobject, } static void zmap_window_container_block_get_property(GObject *gobject, - guint param_id, - GValue *value, - GParamSpec *pspec) + guint param_id, + GValue *value, + GParamSpec *pspec) { ZMapWindowContainerBlock block_data; @@ -479,6 +897,13 @@ static void zmap_window_container_block_destroy(GtkObject *gtkobject) block_data->window = NULL; /* not ours */ + /* I think that the overlay (FooCanvasGroup) cleanup will remove these */ + block_data->mark.top_item = NULL; + block_data->mark.bottom_item = NULL; + /* just zero these for the paranoid... */ + block_data->mark.start = 0.0; + block_data->mark.end = 0.0; + /* compressed and bumped columns are not ours. canvas owns them, just free the lists */ if(block_data->compressed_cols) { @@ -503,3 +928,15 @@ static void zmap_window_container_block_destroy(GtkObject *gtkobject) return ; } + +static void zmap_window_container_block_post_create(ZMapWindowContainerGroup group) +{ + ZMapWindowContainerBlock block; + + block = ZMAP_CONTAINER_BLOCK(group); + + mark_items_create(block, NULL, NULL); + + return ; +} + diff --git a/src/zmapWindow/items/zmapWindowContainerBlock.h b/src/zmapWindow/items/zmapWindowContainerBlock.h index c5b6434c6dbc3fd20a1162a650e669989682aa85..92aa57d8e14a5488c5511ce99de66a3cf834b665 100755 --- a/src/zmapWindow/items/zmapWindowContainerBlock.h +++ b/src/zmapWindow/items/zmapWindowContainerBlock.h @@ -27,9 +27,9 @@ * * Exported functions: See XXXXXXXXXXXXX.h * HISTORY: - * Last edited: Jun 10 14:48 2009 (rds) + * Last edited: Jan 21 22:01 2010 (roy) * Created: Wed Dec 3 08:21:03 2008 (rds) - * CVS info: $Id: zmapWindowContainerBlock.h,v 1.3 2009-06-10 14:00:38 rds Exp $ + * CVS info: $Id: zmapWindowContainerBlock.h,v 1.4 2010-01-22 09:17:43 rds Exp $ *------------------------------------------------------------------- */ @@ -40,6 +40,7 @@ #include <libfoocanvas/libfoocanvas.h> #include <zmapWindowContainerGroup_I.h> #include <zmapWindowContainerFeatureSet.h> +#include <zmapWindowMark_P.h> /* ZMapWindowMark ... */ #define ZMAP_WINDOW_CONTAINER_BLOCK_NAME "ZMapWindowContainerBlock" @@ -72,17 +73,15 @@ void zmapWindowContainerBlockAddBumpedColumn(ZMapWindowContainerBlock block_da GList *zmapWindowContainerBlockRemoveBumpedColumns(ZMapWindowContainerBlock block_data); void zmapWindowContainerBlockMark(ZMapWindowContainerBlock container_block, - GdkColor *mark_colour, - GdkBitmap *mark_stipple, - double start, double end); + ZMapWindowMark mark); void zmapWindowContainerBlockUnmark(ZMapWindowContainerBlock container_block); -void zmapWindowContainerBlockMarkRegion(ZMapWindowContainerBlock block_data, +void zmapWindowContainerBlockFlagRegion(ZMapWindowContainerBlock block_data, ZMapFeatureBlock block); -void zmapWindowContainerBlockMarkRegionForColumn(ZMapWindowContainerBlock container_block, +void zmapWindowContainerBlockFlagRegionForColumn(ZMapWindowContainerBlock container_block, ZMapFeatureBlock block, ZMapWindowContainerFeatureSet container_set); -GList *zmapWindowContainerBlockFilterMarkedColumns(ZMapWindowContainerBlock block_data, - GList *list, int world1, int world2); +GList *zmapWindowContainerBlockFilterFlaggedColumns(ZMapWindowContainerBlock block_data, + GList *list, int world1, int world2); gboolean zmapWindowContainerBlockIsColumnLoaded(ZMapWindowContainerBlock container_block, ZMapWindowContainerFeatureSet container_set, int world1, int world2); diff --git a/src/zmapWindow/items/zmapWindowContainerGroup.c b/src/zmapWindow/items/zmapWindowContainerGroup.c index e1ff9da0c37b47ad2821a38a4b3285bc63669043..c76650929e9161e85c22cea746ef2bdac0e9e228 100755 --- a/src/zmapWindow/items/zmapWindowContainerGroup.c +++ b/src/zmapWindow/items/zmapWindowContainerGroup.c @@ -27,9 +27,9 @@ * * Exported functions: See XXXXXXXXXXXXX.h * HISTORY: - * Last edited: Jun 15 11:37 2009 (rds) + * Last edited: Jan 20 21:46 2010 (roy) * Created: Wed Dec 3 10:02:22 2008 (rds) - * CVS info: $Id: zmapWindowContainerGroup.c,v 1.8 2010-01-19 06:29:59 rds Exp $ + * CVS info: $Id: zmapWindowContainerGroup.c,v 1.9 2010-01-22 09:17:43 rds Exp $ *------------------------------------------------------------------- */ @@ -261,6 +261,8 @@ ZMapWindowContainerGroup zmapWindowContainerGroupCreateFromFoo(FooCanvasGroup overlay = foo_canvas_item_new(group, ZMAP_TYPE_CONTAINER_OVERLAY, NULL); + if(ZMAP_CONTAINER_GROUP_GET_CLASS(container)->post_create) + (ZMAP_CONTAINER_GROUP_GET_CLASS(container)->post_create)(container); } return container; diff --git a/src/zmapWindow/items/zmapWindowContainerUtils.c b/src/zmapWindow/items/zmapWindowContainerUtils.c index 92943115788217d991d9d23e47d1b9bb1168a536..3c2c257129c8cdc138afd06d9a3f5776e7c443df 100755 --- a/src/zmapWindow/items/zmapWindowContainerUtils.c +++ b/src/zmapWindow/items/zmapWindowContainerUtils.c @@ -27,9 +27,9 @@ * * Exported functions: See XXXXXXXXXXXXX.h * HISTORY: - * Last edited: Oct 16 14:41 2009 (edgrif) + * Last edited: Jan 20 09:21 2010 (roy) * Created: Tue Apr 28 16:10:46 2009 (rds) - * CVS info: $Id: zmapWindowContainerUtils.c,v 1.8 2010-01-19 12:36:53 mh17 Exp $ + * CVS info: $Id: zmapWindowContainerUtils.c,v 1.9 2010-01-22 09:17:43 rds Exp $ *------------------------------------------------------------------- */ @@ -70,6 +70,13 @@ static void eachContainer(gpointer data, gpointer user_data); static void set_column_lists_cb(ZMapWindowContainerGroup container, FooCanvasPoints *points, ZMapContainerLevelType level, gpointer user_data); +/*! + * \brief Checks whether the container is valid + * + * \param any_group Any FooCanvas group is accepted here. + * + * \return boolean describing validity TRUE = valid, FALSE = invalid + */ gboolean zmapWindowContainerUtilsIsValid(FooCanvasGroup *any_group) { @@ -80,6 +87,36 @@ gboolean zmapWindowContainerUtilsIsValid(FooCanvasGroup *any_group) return valid; } +void zmapWindowContainerUtilsPrint(FooCanvasGroup *any_group) +{ + + if(ZMAP_IS_CONTAINER_GROUP(any_group)) + { + ZMapWindowContainerGroup this_container; + + this_container = ZMAP_CONTAINER_GROUP(any_group); + + switch(this_container->level) + { + case ZMAPCONTAINER_LEVEL_ROOT: printf("context: "); break; + case ZMAPCONTAINER_LEVEL_ALIGN: printf("align: "); break; + case ZMAPCONTAINER_LEVEL_BLOCK: printf("block: "); break; + case ZMAPCONTAINER_LEVEL_STRAND: printf("strand: "); break; + case ZMAPCONTAINER_LEVEL_FEATURESET: printf("featureset: "); break; + default: + break; + } + + printf("\n"); + } + else + { + printf("Just a regular foocanvas group\n"); + } + + return ; +} + /* gross tree access. any item -> container group */ ZMapWindowContainerGroup zmapWindowContainerChildGetParent(FooCanvasItem *item) @@ -390,7 +427,10 @@ FooCanvasItem *zmapWindowContainerGetNthFeatureItem(ZMapWindowContainerGroup con } -/* Given any item that is a direct child of a column group (e.g. not a subfeature), returns +/*! + * \brief Iterate through feature items + * + * Given any item that is a direct child of a column group (e.g. not a subfeature), returns * the previous or next item that optionally satisfies item_test_func_cb(). The function skips * over items that fail these tests. * @@ -400,7 +440,7 @@ FooCanvasItem *zmapWindowContainerGetNthFeatureItem(ZMapWindowContainerGroup con * If no item can be found then the original will be returned, note that if item_test_func_cb() * was specified and the original item does not satisfy item_test_func_cb() then NULL is returned. * - * */ + * */ FooCanvasItem *zmapWindowContainerGetNextFeatureItem(FooCanvasItem *orig_item, ZMapContainerItemDirection direction, gboolean wrap, zmapWindowContainerItemTestCallback item_test_func_cb, diff --git a/src/zmapWindow/zmapWindow.c b/src/zmapWindow/zmapWindow.c index bf897838d4f3dc7576e517de73f71d9bf657422a..435ceb60306f1f150aa4ce8a078c7c02a9cdd0b4 100755 --- a/src/zmapWindow/zmapWindow.c +++ b/src/zmapWindow/zmapWindow.c @@ -28,7 +28,7 @@ * HISTORY: * Last edited: Jan 21 14:54 2010 (edgrif) * Created: Thu Jul 24 14:36:27 2003 (edgrif) - * CVS info: $Id: zmapWindow.c,v 1.302 2010-01-21 15:21:31 edgrif Exp $ + * CVS info: $Id: zmapWindow.c,v 1.303 2010-01-22 09:16:04 rds Exp $ *------------------------------------------------------------------- */ @@ -3694,7 +3694,7 @@ void zmapWindowFetchData(ZMapWindow window, ZMapFeatureBlock block, block->parent->unique_id, block->unique_id, 0, 0, 0, 0))) { - column_name_list = zmapWindowContainerBlockFilterMarkedColumns((ZMapWindowContainerBlock)block_group, + column_name_list = zmapWindowContainerBlockFilterFlaggedColumns((ZMapWindowContainerBlock)block_group, column_name_list, fetch_data->start, fetch_data->end); @@ -3762,7 +3762,7 @@ GList *zmapWindowDeferredColumnsInMark(ZMapWindow window) if(zmapWindowWorld2SeqCoords(window, x1, y1, x2, y2, &block_group, &wy1, &wy2)) { - list = zmapWindowContainerBlockFilterMarkedColumns((ZMapWindowContainerBlock)block_group, + list = zmapWindowContainerBlockFilterFlaggedColumns((ZMapWindowContainerBlock)block_group, list, wy1, wy2); } } @@ -3836,7 +3836,7 @@ GList *zmapWindowDeferredColumnsInBlock(ZMapWindow window) block_any->struct_type == ZMAPFEATURE_STRUCT_BLOCK) { block = (ZMapFeatureBlock)block_any; - list = zmapWindowContainerBlockFilterMarkedColumns(container_block, + list = zmapWindowContainerBlockFilterFlaggedColumns(container_block, list, block->block_to_sequence.q1, block->block_to_sequence.q2); diff --git a/src/zmapWindow/zmapWindowColConfig.c b/src/zmapWindow/zmapWindowColConfig.c index b9b73818e4617d8d05538c3e52f5fdda1b814749..71689e8dc2e32bfb917d18f6e0cef2495ac10dac 100755 --- a/src/zmapWindow/zmapWindowColConfig.c +++ b/src/zmapWindow/zmapWindowColConfig.c @@ -28,7 +28,7 @@ * HISTORY: * Last edited: Jan 19 18:35 2010 (edgrif) * Created: Thu Mar 2 09:07:44 2006 (edgrif) - * CVS info: $Id: zmapWindowColConfig.c,v 1.33 2010-01-19 18:35:45 edgrif Exp $ + * CVS info: $Id: zmapWindowColConfig.c,v 1.34 2010-01-22 09:16:37 rds Exp $ *------------------------------------------------------------------- */ @@ -1271,12 +1271,15 @@ static FooCanvasGroup *configure_get_point_block_container(ColConfigure configur if(mark_set) { +#ifdef REMOVE_WORLD2SEQ double x1, y1, x2, y2; int wy1,wy2; zmapWindowMarkGetWorldRange(window->mark, &x1, &y1, &x2, &y2); zmapWindowWorld2SeqCoords(window, x1, y1, x2, y2, &block, &wy1, &wy2); +#endif + block = (FooCanvasGroup *)zmapWindowMarkGetCurrentBlockContainer(window->mark); } else { diff --git a/src/zmapWindow/zmapWindowDrawFeatures.c b/src/zmapWindow/zmapWindowDrawFeatures.c index e33917ba98b50d3a497cacb7f7cfe6930ee4ad37..0c3a7b525b996f4a9e60a1260a7fefa15f143785 100755 --- a/src/zmapWindow/zmapWindowDrawFeatures.c +++ b/src/zmapWindow/zmapWindowDrawFeatures.c @@ -28,7 +28,7 @@ * HISTORY: * Last edited: Dec 11 08:32 2009 (edgrif) * Created: Thu Jul 29 10:45:00 2004 (rnc) - * CVS info: $Id: zmapWindowDrawFeatures.c,v 1.256 2010-01-19 13:53:23 mh17 Exp $ + * CVS info: $Id: zmapWindowDrawFeatures.c,v 1.257 2010-01-22 09:17:43 rds Exp $ *------------------------------------------------------------------- */ @@ -69,7 +69,7 @@ typedef struct _ZMapCanvasDataStruct * ORDERING/PLACEMENT MECHANISM.... */ /* Records current positional information. */ double curr_x_offset ; - double curr_y_offset ; + //double curr_y_offset ; /* Records current canvas item groups, these are the direct parent groups of the display @@ -654,7 +654,7 @@ void zmapWindowDrawFeatureSet(ZMapWindow window, block_container = zmapWindowContainerUtilsGetParentLevel(column_container_parent, ZMAPCONTAINER_LEVEL_BLOCK); - zmapWindowContainerBlockMarkRegionForColumn((ZMapWindowContainerBlock)block_container, + zmapWindowContainerBlockFlagRegionForColumn((ZMapWindowContainerBlock)block_container, (ZMapFeatureBlock)feature_set->parent, (ZMapWindowContainerFeatureSet)column_container_parent); } @@ -1338,7 +1338,7 @@ static ZMapFeatureContextExecuteStatus windowDrawContextCB(GQuark key_id, /* THIS MUST GO.t...because we will have aligns that .sigh.do not start at 0 one day.... */ /* Always reset the aligns to start at y = 0. */ - canvas_data->curr_y_offset = 0.0 ; + //canvas_data->curr_y_offset = 0.0 ; x = canvas_data->curr_x_offset ; y = canvas_data->full_context->sequence_to_parent.c1 ; @@ -1407,7 +1407,7 @@ static ZMapFeatureContextExecuteStatus windowDrawContextCB(GQuark key_id, feature_block->unique_id); /* Always set y offset to be top of current block. */ - canvas_data->curr_y_offset = feature_block->block_to_sequence.t1 ; + // canvas_data->curr_y_offset = feature_block->block_to_sequence.t1 ; if ((block_hash_item = zmapWindowFToIFindItemFull(window->context_to_item, canvas_data->curr_alignment->unique_id, @@ -1463,7 +1463,7 @@ static ZMapFeatureContextExecuteStatus windowDrawContextCB(GQuark key_id, if(feature_block->features_start != 0 && feature_block->features_end != 0) { - zmapWindowContainerBlockMarkRegion(container_block, feature_block); + zmapWindowContainerBlockFlagRegion(container_block, feature_block); } diff --git a/src/zmapWindow/zmapWindowItem.c b/src/zmapWindow/zmapWindowItem.c index 4149ea863d5fdc32667aacead8922999557a5078..c082fe4dff8b4c92619d8af6cf3c4519d6e6cca5 100755 --- a/src/zmapWindow/zmapWindowItem.c +++ b/src/zmapWindow/zmapWindowItem.c @@ -28,7 +28,7 @@ * HISTORY: * Last edited: Jan 21 14:54 2010 (edgrif) * Created: Thu Sep 8 10:37:24 2005 (edgrif) - * CVS info: $Id: zmapWindowItem.c,v 1.123 2010-01-21 15:21:35 edgrif Exp $ + * CVS info: $Id: zmapWindowItem.c,v 1.124 2010-01-22 09:17:43 rds Exp $ *------------------------------------------------------------------- */ @@ -2109,8 +2109,15 @@ static gboolean areas_intersect_gt_threshold(AreaStruct *area_1, AreaStruct *are threshold = 1.0 - threshold; else threshold = 0.0; /* 100% overlap only */ - - if((aI <= (a1 * (1.0 + threshold))) && (aI >= (a1 * (1.0 - threshold)))) + + if(inter.x1 >= area_1->x1 && + inter.y1 >= area_1->y1 && + inter.x2 <= area_1->x2 && + inter.y2 <= area_1->y2) + { + above_threshold = TRUE; /* completely contained */ + } + else if((aI <= (a1 * (1.0 + threshold))) && (aI >= (a1 * (1.0 - threshold)))) above_threshold = TRUE; else zMapLogWarning("%s", "intersection below threshold"); diff --git a/src/zmapWindow/zmapWindowMark.c b/src/zmapWindow/zmapWindowMark.c index beab08ad20af3594797c31f474cfa5e3cf17dfcd..b7cf9faf3b6f602e311e6d22a37882d045473b08 100755 --- a/src/zmapWindow/zmapWindowMark.c +++ b/src/zmapWindow/zmapWindowMark.c @@ -27,48 +27,62 @@ * * Exported functions: See zmapWindow_P.h * HISTORY: - * Last edited: Oct 6 10:11 2009 (edgrif) + * Last edited: Jan 22 22:02 2010 (roy) * Created: Tue Jan 16 09:51:19 2007 (rds) - * CVS info: $Id: zmapWindowMark.c,v 1.19 2009-10-14 16:48:39 edgrif Exp $ + * CVS info: $Id: zmapWindowMark.c,v 1.20 2010-01-22 09:17:43 rds Exp $ *------------------------------------------------------------------- */ #include <ZMap/zmapUtils.h> -#include <zmapWindow_P.h> +#include <zmapWindow_P.h> /* ZMapWindow */ +#include <zmapWindowMark_P.h> #include <zmapWindowCanvasItem.h> #include <zmapWindowContainerUtils.h> +#include <zmapWindowContainerBlock.h> + +#define mark_bitmap_width 16 +#define mark_bitmap_height 4 -/* User can set a range (perhaps by selecting an item) for operations like zooming and bump options. */ typedef struct _ZMapWindowMarkStruct { - ZMapMagic magic; - gboolean mark_set ; - ZMapWindow window ; - FooCanvasItem *range_item ; - ZMapWindowContainerBlock block_container; - ZMapFeatureBlock block ; - double world_x1, world_y1, world_x2, world_y2 ; - int range_top, range_bottom ; - GdkColor colour ; - GdkBitmap *stipple ; - FooCanvasGroup *range_group ; - FooCanvasItem *top_range_item ; - FooCanvasItem *bottom_range_item ; + ZMapMagic magic ; + + ZMapWindowContainerBlock block_container ; /*! The block the mark is set on. This might need to become a list of */ + ZMapWindow window ; /*! mark needs access to the ZMapWindow without having to pass it in. */ + FooCanvasItem *mark_src_item ; /*! This is the item that is the src of the mark. Can be NULL. */ + + /*! world coords of the mark. */ + double world_x1 ; + double world_y1 ; + double world_x2 ; + double world_y2 ; + + /* These are block sequence coordinates */ + int seq_start ; /*! start of the mark in seq coords (of block) */ + int seq_end ; /*! end of the mark in seq coords (of block) */ + + GdkColor colour ; /*! colour used for the mark */ + GdkBitmap *stipple ; /*! stipple used for the mark */ + + gboolean mark_set ; /*! internal flag for whether mark is set. */ + double margin ; } ZMapWindowMarkStruct ; -/* Used to hold highlight information for the hightlight callback function. */ -typedef struct -{ - ZMapWindow window ; - ZMapWindowMark mark ; - gboolean highlight ; -} HighlightStruct, *Highlight ; + +static void markItem(ZMapWindowMark mark, FooCanvasItem *item, gboolean set_mark) ; +static void markRange(ZMapWindowMark mark, double y1, double y2) ; +static void mark_block_cb(ZMapWindowContainerGroup container, FooCanvasPoints *points, + ZMapContainerLevelType level, gpointer user_data); -#define mark_bitmap_width 16 -#define mark_bitmap_height 4 -static char mark_bitmap_bits[] = +/* Some static global declarations... Oh joy. */ + +/*! mark_magic_G is a simple pointer to check validity of a ZMapWindowMark */ +ZMAP_MAGIC_NEW(mark_magic_G, ZMapWindowMarkStruct) ; + +/*! mark_bitmap_bits_G is the definition of the default stipple. */ +static char mark_bitmap_bits_G[] = { 0x11, 0x11, 0x22, 0x22, @@ -77,13 +91,11 @@ static char mark_bitmap_bits[] = } ; -static void markItem(ZMapWindowMark mark, FooCanvasItem *item, gboolean set_mark) ; -static void markFuncCB(gpointer data, gpointer user_data) ; -static void markRange(ZMapWindowMark mark, double y1, double y2) ; -static void setBoundingBoxColour(ZMapWindowMark mark, FooCanvasItem *item, gboolean highlight) ; + /* - * Set of functions for handling the marked feature or region. + * Set of functions for handling the marked feature or region + * ---------------------------------------------------------- * * Essentially there are two ways to mark, either by marking a feature or * by marking a region. The two are mutually exclusive. @@ -91,14 +103,45 @@ static void setBoundingBoxColour(ZMapWindowMark mark, FooCanvasItem *item, gbool * If a feature is marked then it will be used in a number of window operations * such as zooming and column bumping. * - * + * Details: + * + * - Either mark using a feature item, or using a _world_ coordinate range + * - Using an item leads to 'synchronous' setting of the mark with respect + * to the ZMapWindowContainerBlock that is stored in the mark. + * - Using a region leads to 'asynchronous' setting of the mark with respect + * to the ZMapWindowContainerBlock theat is stored. + * - The items that display the mark are handled in the ZMapWindowContainerBlock + * code. This is the root cause of the sync/async nature. + * - The mark items are stippled using the supplied stipple. + * - The mark items must be resized by some means for long items reasons. + * - The long items cropping/resizing is handled in the ZMapWindowContainerBlock + * code by the update hooks the ZMapWindowContainerGroup interface provides. + * - Initial selection of the correct block (setting by world coord) is again + * done in the container code by way of the update hooks. Selection works + * on a world coord basis. When setting by item the item's parent's parent + * is used. + * - The mark is saved across revcomp, vsplit, hsplit, by the ZMapWindowState + * code and it handles serializing the mark and calling the mark functions. + * - There are a couple of issues to watch out for when multiple blocks get displayed + * - The block_container will need to handle multiple blocks, as will the interface. + * - Selecting the correct block might need thought. I think it's ok as it is, + * but check out the container block code. */ -ZMAP_MAGIC_NEW(mark_magic_G, ZMapWindowMarkStruct) ; -/* The mark is internal to window but other code needs to know its position. */ + + +/*! + * \brief Get the marked region of a window. + * + * \param window The window to get the mark from + * \param start The address to store the start of the mark + * \param end The address to store the end of the mark + * + * \return boolean corresponding to whether mark is set TRUE = set, FALSE = unset + */ gboolean zMapWindowGetMark(ZMapWindow window, int *start, int *end) { gboolean result = FALSE ; @@ -124,9 +167,14 @@ gboolean zMapWindowGetMark(ZMapWindow window, int *start, int *end) return result ; } - - - +/*! + * \brief Create a ZMapWindowMark + * + * \param window The window to create the mark for. + * + * \return The newly allocated ZMapWindowMark, which should be zmapWindowMarkDestroy()d + * when finished with. + */ ZMapWindowMark zmapWindowMarkCreate(ZMapWindow window) { @@ -142,60 +190,100 @@ ZMapWindowMark zmapWindowMarkCreate(ZMapWindow window) mark->window = window ; - mark->range_item = NULL ; + mark->mark_src_item = NULL ; - mark->range_top = mark->range_bottom = 0 ; + mark->seq_start = mark->seq_end = 0 ; + + mark->margin = 0; zmapWindowMarkSetColour(mark, ZMAP_WINDOW_ITEM_MARK) ; - mark->stipple = gdk_bitmap_create_from_data(NULL, &mark_bitmap_bits[0], mark_bitmap_width, mark_bitmap_height) ; + mark->stipple = gdk_bitmap_create_from_data(NULL, &mark_bitmap_bits_G[0], mark_bitmap_width, mark_bitmap_height) ; return mark ; } +/*! + * \brief Access to the state of a mark + * + * This function returns whether the mark is set. + * + * \param mark The mark to interrogate + * + * \return boolean TRUE = set, FALSE = unset + */ gboolean zmapWindowMarkIsSet(ZMapWindowMark mark) { + gboolean result; + zMapAssert(mark && ZMAP_MAGIC_IS_VALID(mark_magic_G, mark->magic)) ; - return mark->mark_set ; + /* marking is 'asynchronous' during redraws for marks with no mark_src_item. */ + /* mark->block_container is only populated for non-SetItem marks when the blocks are drawn. */ + /* including mark->block_container in the isset calculation therefore leads to lost marks + * when save state does a mark is set before the redraw has completed. + */ + /* This is not a problem for MarkSetItem marks as the block_container is known before hand + * and is therefore saved and available any time afterwards to save state. */ + result = (mark->mark_set && mark->block_container); + result = (mark->mark_set); + + if(mark->mark_set) + { + if(mark->mark_src_item) + result = (mark->mark_set && mark->block_container); + else + result = (mark->mark_set); + } + + return result; } +/*! + * \brief Reset the mark i.e. Unmark + * + * \param mark The mark to reset + * + * \return nothing. + */ void zmapWindowMarkReset(ZMapWindowMark mark) { zMapAssert(mark && ZMAP_MAGIC_IS_VALID(mark_magic_G, mark->magic)) ; if (mark->mark_set) { - zmapWindowContainerBlockUnmark(mark->block_container); - - if (mark->range_item) - { - /* undo highlighting */ - markItem(mark, mark->range_item, FALSE) ; + mark->mark_set = FALSE ; - mark->range_item = NULL ; - } + if(mark->block_container) + zmapWindowContainerBlockUnmark(mark->block_container); - mark->range_top = mark->range_bottom = 0 ; + mark->block_container = NULL; - if (mark->range_group) + if (mark->mark_src_item) { - /* Do not destroy the range_group, its belongs to the block container ! */ - zmapWindowLongItemRemove(mark->window->long_items, mark->top_range_item) ; - gtk_object_destroy(GTK_OBJECT(mark->top_range_item)) ; - mark->top_range_item = NULL ; - - zmapWindowLongItemRemove(mark->window->long_items, mark->bottom_range_item) ; - gtk_object_destroy(GTK_OBJECT(mark->bottom_range_item)) ; - mark->bottom_range_item = NULL ; + /* undo highlighting */ + markItem(mark, mark->mark_src_item, FALSE) ; + + mark->mark_src_item = NULL ; } - mark->mark_set = FALSE ; + /* reset all the coords */ + mark->world_x1 = mark->world_x2 = 0.0; + mark->world_y1 = mark->world_y2 = 0.0; + mark->seq_start = mark->seq_end = 0 ; } return ; } +/*! + * \brief Set the colour for the mark + * + * \param mark The mark + * \param colour The colour as a string for gdk_color_parse + * + * \return nothing. + */ void zmapWindowMarkSetColour(ZMapWindowMark mark, char *colour) { zMapAssert(mark && ZMAP_MAGIC_IS_VALID(mark_magic_G, mark->magic)) ; @@ -205,6 +293,13 @@ void zmapWindowMarkSetColour(ZMapWindowMark mark, char *colour) return ; } +/*! + * \brief Get the colour the mark is using. + * + * \param mark The mark + * + * \return rhe GdkColor. + */ GdkColor *zmapWindowMarkGetColour(ZMapWindowMark mark) { zMapAssert(mark && ZMAP_MAGIC_IS_VALID(mark_magic_G, mark->magic)) ; @@ -212,6 +307,43 @@ GdkColor *zmapWindowMarkGetColour(ZMapWindowMark mark) return &(mark->colour) ; } +/*! + * \brief Set the stipple for the mark. + * + * \param mark The mark + * \param stipple The stipple + * + * \return nothing. + */ +void zmapWindowMarkSetStipple(ZMapWindowMark mark, GdkBitmap *stipple) +{ + zMapAssert(mark && ZMAP_MAGIC_IS_VALID(mark_magic_G, mark->magic)) ; + + if(mark->stipple) + { + g_object_unref(G_OBJECT(mark->stipple)) ; + } + + mark->stipple = stipple; + + return ; +} + +/*! + * \brief Get the stipple from the mark + * + * \param mark The mark + * + * \return GdkBitmap. + */ + +GdkBitmap *zmapWindowMarkGetStipple(ZMapWindowMark mark) +{ + zMapAssert(mark && ZMAP_MAGIC_IS_VALID(mark_magic_G, mark->magic)) ; + + return mark->stipple ; +} + /* Mark an item, the marking must be done explicitly, it is unaffected by highlighting. * Note that the item must be a feature item. * @@ -227,53 +359,68 @@ void zmapWindowMarkSetItem(ZMapWindowMark mark, FooCanvasItem *item) zmapWindowMarkReset(mark) ; - mark->range_item = item ; + mark->mark_src_item = item ; /* We need to get the world coords because the item passed in is likely to be a child of a child * of a.... */ - my_foo_canvas_item_get_world_bounds(mark->range_item, &x1, &y1, &x2, &y2) ; + my_foo_canvas_item_get_world_bounds(mark->mark_src_item, &x1, &y1, &x2, &y2) ; - feature = zmapWindowItemGetFeature(mark->range_item); + feature = zmapWindowItemGetFeature(mark->mark_src_item); zMapAssert(feature) ; - mark->range_top = feature->x1 - 1 ; - mark->range_bottom = feature->x2 + 1 ; + mark->seq_start = feature->x1 - 1 ; + mark->seq_end = feature->x2 + 1 ; - mark->block_container = (ZMapWindowContainerBlock)zmapWindowContainerUtilsItemGetParentLevel(mark->range_item, ZMAPCONTAINER_LEVEL_BLOCK) ; - mark->block = zmapWindowItemGetFeatureBlock(mark->block_container); + mark->block_container = + (ZMapWindowContainerBlock)zmapWindowContainerUtilsItemGetParentLevel(mark->mark_src_item, + ZMAPCONTAINER_LEVEL_BLOCK) ; - markItem(mark, mark->range_item, TRUE) ; + markItem(mark, mark->mark_src_item, TRUE) ; - markRange(mark, y1 - 1, y2 + 1) ; + markRange(mark, y1 - mark->margin, y2 + mark->margin) ; - mark->mark_set = TRUE ; return ; } + +/*! + * \brief Get the item. + * + * \param mark The mark + * + * \return FooCanvasItem that is the source of the mark. + */ FooCanvasItem *zmapWindowMarkGetItem(ZMapWindowMark mark) { zMapAssert(mark && ZMAP_MAGIC_IS_VALID(mark_magic_G, mark->magic)) ; - return mark->range_item ; + return mark->mark_src_item ; } - +/*! + * \brief Set the world range of the mark + * + * \param mark The mark + * \param x1 The start x coord + * \param y1 The start y coord + * \param x2 The end x coord + * \param y2 The end y coord + * + * \return boolean. + */ gboolean zmapWindowMarkSetWorldRange(ZMapWindowMark mark, - double world_x1, double world_y1, double world_x2, double world_y2) + double world_x1, double world_y1, + double world_x2, double world_y2) { - gboolean result ; - FooCanvasGroup *block_grp_out ; double scroll_x1, scroll_x2; - int y1_out, y2_out ; + gboolean result ; zMapAssert(mark); zMapAssert(ZMAP_MAGIC_IS_VALID(mark_magic_G, mark->magic)) ; zmapWindowMarkReset(mark) ; - y1_out = y2_out = 0 ; - /* clamp x to scroll region. Fix RT # 55131 */ zmapWindowGetScrollRegion(mark->window, &scroll_x1, NULL, &scroll_x2, NULL); @@ -290,36 +437,30 @@ gboolean zmapWindowMarkSetWorldRange(ZMapWindowMark mark, if(world_x1 > world_x2) ZMAP_SWAP_TYPE(double, world_x1, world_x2); - if ((result = zmapWindowWorld2SeqCoords(mark->window, world_x1, world_y1, world_x2, world_y2, - &block_grp_out, &y1_out, &y2_out))) - { - double y1, y2, dummy; - - mark->block_container = (ZMapWindowContainerBlock)block_grp_out ; - mark->block = zmapWindowItemGetFeatureBlock(mark->block_container); - mark->world_x1 = world_x1 ; - mark->world_y1 = world_y1 ; - mark->world_x2 = world_x2 ; - mark->world_y2 = world_y2 ; - - mark->range_top = y1_out ; - mark->range_bottom = y2_out ; - y1 = mark->world_y1 ; - y2 = mark->world_y2 ; - foo_canvas_item_w2i(FOO_CANVAS_ITEM(mark->block_container), &dummy, &y1) ; - foo_canvas_item_w2i(FOO_CANVAS_ITEM(mark->block_container), &dummy, &y2) ; - - markRange(mark, y1, y2) ; + mark->world_x1 = world_x1 ; + mark->world_y1 = world_y1 ; + mark->world_x2 = world_x2 ; + mark->world_y2 = world_y2 ; + + mark->mark_set = result = TRUE ; - mark->mark_set = TRUE ; - } - else - zMapLogWarning("%s", "zmapWindowWorld2SeqCoords failed, possibly due to foo_canvas_get_item_at bug."); + markRange(mark, world_y1, world_y2) ; return result ; } +/*! + * \brief Get the world range of the mark + * + * \param mark The mark + * \param x1 Address to store the start x coord + * \param y1 Address to store the start y coord + * \param x2 Address to store the end x coord + * \param y2 Address to store the end y coord + * + * \return boolean. + */ gboolean zmapWindowMarkGetWorldRange(ZMapWindowMark mark, double *world_x1, double *world_y1, double *world_x2, double *world_y2) { @@ -334,11 +475,15 @@ gboolean zmapWindowMarkGetWorldRange(ZMapWindowMark mark, *world_x2 = mark->world_x2 ; *world_y2 = mark->world_y2 ; - if(mark->range_item) + +#warning THIS_MUST_BE_CHECKED_FOR_CORRECTNESS + /* I feel this has got to be wrong somehow. I bet this is a + * misguided Ext2Zero, i2w or such like call */ + if(mark->mark_src_item) { /* See the markRange() call in zmapWindowMarkSetItem() */ - (*world_y2)--; - (*world_y1)++; + (*world_y2) -= mark->margin; + (*world_y1) += mark->margin; } result = TRUE ; @@ -347,6 +492,15 @@ gboolean zmapWindowMarkGetWorldRange(ZMapWindowMark mark, return result ; } +/*! + * \brief Get the sequence range of the mark + * + * \param mark The mark + * \param start The start coord + * \param end The end coord + * + * \return boolean. + */ gboolean zmapWindowMarkGetSequenceRange(ZMapWindowMark mark, int *start, int *end) { gboolean result = FALSE ; @@ -355,8 +509,8 @@ gboolean zmapWindowMarkGetSequenceRange(ZMapWindowMark mark, int *start, int *en if (mark->mark_set) { - *start = mark->range_top ; - *end = mark->range_bottom ; + *start = mark->seq_start ; + *end = mark->seq_end ; result = TRUE ; } @@ -364,6 +518,80 @@ gboolean zmapWindowMarkGetSequenceRange(ZMapWindowMark mark, int *start, int *en return result ; } +/*! + * \brief Get the current block container that is marked + * + * \param mark The mark + * + * \return container block or NULL. + */ +ZMapWindowContainerGroup zmapWindowMarkGetCurrentBlockContainer(ZMapWindowMark mark) +{ + ZMapWindowContainerGroup block = NULL; + + if(mark->mark_set) + { + block = (ZMapWindowContainerGroup)mark->block_container; + } + + return block; +} + +/*! + * \brief Not for general use. + * + * It does not perform any marking, nor control any marking. It is only called from + * the zmapWindowContainerBlock code when it has matched a mark area to its area. + * + */ +gboolean zmapWindowMarkSetBlockContainer(ZMapWindowMark mark, ZMapWindowContainerGroup container, + double sequence_start, double sequence_end, + double x1, double y1, double x2, double y2) +{ + ZMapWindowContainerBlock block_container; + gboolean result = FALSE; + + if(mark->mark_set) + { + if(ZMAP_IS_CONTAINER_BLOCK(container) && !mark->block_container) + { + block_container = (ZMapWindowContainerBlock)container; + mark->block_container = block_container; + mark->seq_start = (int)sequence_start; + mark->seq_end = (int)sequence_end; + + result = TRUE; + } + + /* This seems like a strange thing to do, but if we have set + * an item the x coords might not be set. */ + if(mark->world_x1 != x1 && mark->world_x1 == 0.0) + mark->world_x1 = x1; + + if(mark->world_x2 != x2 && mark->world_x2 == 0.0) + mark->world_x2 = x2; + + /* I also want to check we have the correct y coords. */ + if(mark->world_y1 != y1) + zMapLogWarning("mark start coord (%f) does not match parameter (%f)", mark->world_y1, y1); + + if(mark->world_y2 != y2) + zMapLogWarning("mark end coord (%f) does not match parameter (%f)", mark->world_y2, y2); + } + + return result; +} + + +/*! + * \brief Free the memory used by a ZMapWindowMark + * + * The should be changed to return a NULL ZMapWindowMark pointer. + * + * \param mark The mark to free. + * + * \return nothing + */ void zmapWindowMarkDestroy(ZMapWindowMark mark) { zMapAssert(mark && ZMAP_MAGIC_IS_VALID(mark_magic_G, mark->magic)) ; @@ -387,56 +615,37 @@ void zmapWindowMarkDestroy(ZMapWindowMark mark) /* Mark/unmark an item with a highlight colour. */ +/* + * The bounding_box is a bit of a hack to support marking objects, + * a better way would be to use masks as overlays but I don't have time just + * now. ALSO....if you put highlighting over the top of the feature you won't + * be able to click on it any more....agh....something to solve..... + * + * This is solved by the ZMapWindowCanvasItems + */ static void markItem(ZMapWindowMark mark, FooCanvasItem *item, gboolean set_mark) { - FooCanvasItem *parent ; - - parent = item ; - - setBoundingBoxColour(mark, parent, set_mark) ; - - return ; - - if (FOO_IS_CANVAS_GROUP(parent)) + if(set_mark) { - HighlightStruct highlight_data = {NULL} ; - FooCanvasGroup *group = FOO_CANVAS_GROUP(parent) ; - - highlight_data.mark = mark ; - highlight_data.highlight = set_mark ; + GdkColor *mark_colour; + GdkBitmap *mark_stipple; - g_list_foreach(group->item_list, markFuncCB, (void *)&highlight_data) ; + mark_colour = zmapWindowMarkGetColour(mark); + mark_stipple = mark->stipple; + + zMapWindowCanvasItemMark((ZMapWindowCanvasItem)item, mark_colour, mark_stipple); } else - { - } - - return ; -} - - -/* This is a g_list callback function. */ -static void markFuncCB(gpointer data, gpointer user_data) -{ - FooCanvasItem *item = (FooCanvasItem *)data ; - Highlight highlight = (Highlight)user_data ; - - setBoundingBoxColour(highlight->mark, item, highlight->highlight) ; + zMapWindowCanvasItemUnmark((ZMapWindowCanvasItem)item); return ; } - /* The range markers are implemented as overlays in the block container. This makes sense because * a mark is relevant only to its parent block. */ static void markRange(ZMapWindowMark mark, double y1, double y2) { - double block_x1, block_y1, block_x2, block_y2, tmp_y1, tmp_y2 ; - - foo_canvas_item_get_bounds(FOO_CANVAS_ITEM(mark->block_container), &block_x1, &block_y1, &block_x2, &block_y2) ; - - zmapWindowExt2Zero(&block_x1, &block_x2) ; - zmapWindowExt2Zero(&block_y1, &block_y2) ; + double block_y1, block_y2, tmp_y1, tmp_y2 ; tmp_y1 = y1 ; tmp_y2 = y2 ; @@ -453,6 +662,7 @@ static void markRange(ZMapWindowMark mark, double y1, double y2) tmp_y1 = block_y1 ; block_y1 = tmp ; } + if (block_y2 < tmp_y2) { double tmp ; @@ -462,46 +672,48 @@ static void markRange(ZMapWindowMark mark, double y1, double y2) block_y2 = tmp ; } - { - GdkColor *mark_colour; - GdkBitmap *mark_stipple; - - mark_colour = zmapWindowMarkGetColour(mark); - mark_stipple = mark->stipple; - - zmapWindowContainerBlockMark(mark->block_container, mark_colour, mark_stipple, tmp_y1, tmp_y2); - } - mark->world_y1 = y1; mark->world_y2 = y2; + mark->mark_set = TRUE ; + + if(mark->block_container) + { + /* Hey, we've got the block. We'll just mark that block rather + * than go to each one and potentially mark one. */ + zmapWindowContainerBlockMark(mark->block_container, mark); + } + else + { + /* Potentially we could mark the wrong block, or multiple blocks. + * marking multiple blocks that have intersections in y axis is + * probably not bad and might be desired... Actually thinking + * about the code this is probably what would happen. + */ + zmapWindowContainerUtilsExecute(mark->window->feature_root_group, + ZMAPCONTAINER_LEVEL_BLOCK, + mark_block_cb, + mark); + } return ; } - -/* - * The bounding_box is a bit of a hack to support marking objects, - * a better way would be to use masks as overlays but I don't have time just - * now. ALSO....if you put highlighting over the top of the feature you won't - * be able to click on it any more....agh....something to solve..... - * - */ -static void setBoundingBoxColour(ZMapWindowMark mark, FooCanvasItem *item, gboolean highlight) +static void mark_block_cb(ZMapWindowContainerGroup container, FooCanvasPoints *points, + ZMapContainerLevelType level, gpointer user_data) { - if(highlight) + switch(level) { - GdkColor *mark_colour; - GdkBitmap *mark_stipple; - - mark_colour = zmapWindowMarkGetColour(mark); - mark_stipple = mark->stipple; - - zMapWindowCanvasItemMark((ZMapWindowCanvasItem)item, mark_colour, mark_stipple); + case ZMAPCONTAINER_LEVEL_BLOCK: + { + ZMapWindowContainerBlock block = (ZMapWindowContainerBlock)container; + ZMapWindowMark mark = (ZMapWindowMark)user_data; + + zmapWindowContainerBlockMark(block, mark); + } + break; + default: + break; } - else - zMapWindowCanvasItemUnmark((ZMapWindowCanvasItem)item); - - return ; } diff --git a/src/zmapWindow/zmapWindow_P.h b/src/zmapWindow/zmapWindow_P.h index 1098040f64ee6f6574a725275196d34a4bbdb3ab..62de42a6326d1843efb9b1e22de283dcca686629 100755 --- a/src/zmapWindow/zmapWindow_P.h +++ b/src/zmapWindow/zmapWindow_P.h @@ -25,9 +25,9 @@ * Description: Defines internal interfaces/data structures of zMapWindow. * * HISTORY: - * Last edited: Jan 21 14:48 2010 (edgrif) + * Last edited: Jan 22 20:45 2010 (roy) * Created: Fri Aug 1 16:45:58 2003 (edgrif) - * CVS info: $Id: zmapWindow_P.h,v 1.250 2010-01-21 15:21:35 edgrif Exp $ + * CVS info: $Id: zmapWindow_P.h,v 1.251 2010-01-22 09:17:43 rds Exp $ *------------------------------------------------------------------- */ #ifndef ZMAP_WINDOW_P_H @@ -43,6 +43,8 @@ #include <zmapWindowTextPositioner.h> #include <zmapWindowContainerGroup.h> #include <zmapWindowContainerUtils.h> + + /* * This section details data that we attacht to the foocanvas items that represent * contexts, aligns etc. Each data structure is accessed via a key given by the @@ -429,8 +431,6 @@ typedef struct _ZMapWindowZoomControlStruct *ZMapWindowZoomControl ; typedef struct _ZMapWindowFocusStruct *ZMapWindowFocus ; -typedef struct _ZMapWindowMarkStruct *ZMapWindowMark ; - typedef struct _ZMapWindowLongItemsStruct *ZMapWindowLongItems ; typedef struct _ZMapWindowFToIFactoryStruct *ZMapWindowFToIFactory ; @@ -1152,21 +1152,6 @@ void zmapWindowItemCentreOnItemSubPart(ZMapWindow window, FooCanvasItem *item, gboolean zmapWindowItemIsOnScreen(ZMapWindow window, FooCanvasItem *item, gboolean completely) ; void zmapWindowScrollToItem(ZMapWindow window, FooCanvasItem *item) ; -ZMapWindowMark zmapWindowMarkCreate(ZMapWindow window) ; -gboolean zmapWindowMarkIsSet(ZMapWindowMark mark) ; -void zmapWindowMarkReset(ZMapWindowMark mark) ; -void zmapWindowMarkSetColour(ZMapWindowMark mark, char *colour) ; -GdkColor *zmapWindowMarkGetColour(ZMapWindowMark mark) ; -void zmapWindowMarkSetItem(ZMapWindowMark mark, FooCanvasItem *item) ; -FooCanvasItem *zmapWindowMarkGetItem(ZMapWindowMark mark) ; -gboolean zmapWindowMarkSetWorldRange(ZMapWindowMark mark, - double world_x1, double world_y1, double world_x2, double world_y2) ; -gboolean zmapWindowMarkGetWorldRange(ZMapWindowMark mark, - double *world_x1, double *world_y1, - double *world_x2, double *world_y2) ; -gboolean zmapWindowMarkGetSequenceRange(ZMapWindowMark mark, int *start, int *end) ; -void zmapWindowMarkDestroy(ZMapWindowMark mark) ; - /*!-------------------------------------------------------------------!