Пример #1
0
/*! \brief Return the bounds of the given GList of objects.
 *  \par Given a list of objects, calcule the bounds coordinates.
 *  \param [in]  toplevel The TOPLEVEL structure.
 *  \param [in]  head   The list of objects to look the bounds for.
 *  \param [out] left   pointer to the left coordinate of the object.
 *  \param [out] top    pointer to the top coordinate of the object.
 *  \param [out] right  pointer to the right coordinate of the object.
 *  \param [out] bottom pointer to the bottom coordinate of the object.
 *  \return If any bounds were found for the list of objects
 *  \retval 0 No bounds were found
 *  \retval 1 Bound was found
 */
int world_get_object_glist_bounds(TOPLEVEL *toplevel, const GList *head,
                                  int *left, int *top, int *right, int *bottom)
{
  const GList *s_current=NULL;
  OBJECT *o_current=NULL;
  int rleft, rtop, rright, rbottom;
  int found = 0;

  s_current = head;

  /* Find the first object with bounds, and set the bounds variables, then expand as necessary */
  while ( s_current != NULL ) {
    o_current = (OBJECT *) s_current->data;

    /* Sanity check */
    g_return_val_if_fail ((o_current != NULL), found);

    if ( world_get_single_object_bounds( toplevel, o_current, &rleft, &rtop, &rright, &rbottom) ) {
      if ( found ) {
        *left = min( *left, rleft );
        *top = min( *top, rtop );
        *right = max( *right, rright );
        *bottom = max( *bottom, rbottom );
      } else {
        *left = rleft;
        *top = rtop;
        *right = rright;
        *bottom = rbottom;
        found = 1;
      }
    }
    s_current = g_list_next (s_current);
  }
  return found;
}
Пример #2
0
/*! \brief Find the objects in a given region
 *
 *  \par Function Description
 *  Finds the objects which are inside, or intersect
 *  the passed box shaped region.
 *
 *  \param [in] toplevel  The TOPLEVEL object.
 *  \param [in] page      The PAGE to find objects on.
 *  \param [in] rects     The BOX regions to check.
 *  \param [in] n_rects   The number of regions.
 *  \return The GList of OBJECTs in the region.
 */
GList *s_page_objects_in_regions (TOPLEVEL *toplevel, PAGE *page,
                                  BOX *rects, int n_rects)
{
  GList *iter;
  GList *list = NULL;
  int i;

  for (iter = page->_object_list; iter != NULL; iter = g_list_next (iter)) {
    OBJECT *object = iter->data;

    for (i = 0; i < n_rects; i++) {
      int left, top, right, bottom;

      if (world_get_single_object_bounds (toplevel, object,
                                          &left, &top, &right, &bottom) &&
          right  >= rects[i].lower_x &&
          left   <= rects[i].upper_x &&
          top    <= rects[i].upper_y &&
          bottom >= rects[i].lower_y) {
        list = g_list_prepend (list, object);
        break;
      }
    }
  }

  list = g_list_reverse (list);
  return list;
}
Пример #3
0
/*! \brief Tests a if a given OBJECT was hit at a given set of coordinates
 *
 *  \par Function Description
 *  Tests a if a given OBJECT was hit at a given set of coordinates. If an
 *  object is not selectable (e.g. it is locked), or it is invisible and
 *  not being rendered, this function will return FALSE.
 *
 *  \param [in] w_current         The GschemToplevel object.
 *  \param [in] object            The OBJECT being hit-tested.
 *  \param [in] w_x               The X coordinate to test (in world coords).
 *  \param [in] w_y               The Y coordinate to test (in world coords).
 *  \param [in] w_slack           The slack applied to the hit-test.
 *
 *  \returns TRUE if the OBJECT was hit, otherwise FALSE.
 */
static gboolean
is_object_hit (GschemToplevel *w_current, OBJECT *object,
               int w_x, int w_y, int w_slack)
{
  int left, top, right, bottom;

  if (!object->selectable)
    return FALSE;

  /* We can't hit invisible (text) objects unless show_hidden_text is active.
   */
  if (!o_is_visible (object) && !w_current->toplevel->show_hidden_text)
    return FALSE;

  /* Do a coarse test first to avoid computing distances for objects ouside
   * of the hit range.
   */
  if (!world_get_single_object_bounds(w_current->toplevel, object,
                                      &left, &top, &right, &bottom) ||
      !inside_region (left  - w_slack, top    - w_slack,
                      right + w_slack, bottom + w_slack,
                      w_x, w_y))
    return FALSE;

  return (o_shortest_distance (w_current->toplevel, object, w_x, w_y) < w_slack);
}
Пример #4
0
/*! \brief find the closest possible location to connect to
 *  \par Function Description
 *  This function calculates the distance to all connectable objects
 *  and searches the closest connection point.
 *  It searches for pins, nets and busses.
 *
 *  The connection point is stored in GschemToplevel->magnetic_wx and
 *  GschemToplevel->magnetic_wy. If no connection is found. Both variables
 *  are set to -1.
 */
void o_net_find_magnetic(GschemToplevel *w_current,
			 int w_x, int w_y)
{
  int x1, x2, y1, y2, min_x, min_y;
  double mindist, minbest, dist1, dist2;
  double weight, min_weight;
  int magnetic_reach = 0;
  OBJECT *o_current;
  OBJECT *o_magnetic = NULL;
  GList *object_list, *iter1, *iter2;

  GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current);
  g_return_if_fail (page_view != NULL);

  PAGE *page = gschem_page_view_get_page (page_view);
  g_return_if_fail (page != NULL);

  minbest = min_x = min_y = 0;
  min_weight = 0;

  /* max distance of all the different reaches */
  magnetic_reach = max(MAGNETIC_PIN_REACH, MAGNETIC_NET_REACH);
  magnetic_reach = max(magnetic_reach, MAGNETIC_BUS_REACH);

  object_list = g_list_append (NULL, page->connectible_list);

  for (iter1 = object_list; iter1 != NULL; iter1 = g_list_next(iter1)) {
    for (iter2 = (GList*) iter1->data; iter2 != NULL; iter2 = g_list_next(iter2)) {
      int left, top, right, bottom;
      o_current = (OBJECT*) iter2->data;

      if (!world_get_single_object_bounds(page->toplevel, o_current,
                                          &left, &top, &right, &bottom) ||
          !visible (w_current, left, top, right, bottom))
	continue; /* skip invisible objects */

      if (o_current->type == OBJ_PIN) {
	min_x = o_current->line->x[o_current->whichend];
	min_y = o_current->line->y[o_current->whichend];

	mindist = hypot(w_x - min_x, w_y - min_y);
	weight = mindist / MAGNETIC_PIN_WEIGHT;
      }

      else if (o_current->type == OBJ_NET
	       || o_current->type == OBJ_BUS) {
	/* we have 3 possible points to connect:
	   2 endpoints and 1 midpoint point */
	x1 = o_current->line->x[0];
	y1 = o_current->line->y[0];
	x2 = o_current->line->x[1];
	y2 = o_current->line->y[1];
	/* endpoint tests */
	dist1 = hypot(w_x - x1, w_y - y1);
	dist2 = hypot(w_x - x2, w_y - y2);
	if (dist1 < dist2) {
	  min_x = x1;
	  min_y = y1;
	  mindist = dist1;
	}
	else {
	  min_x = x2;
	  min_y = y2;
	  mindist = dist2;
	}

	/* midpoint tests */
	if ((x1 == x2)  /* vertical net */
	    && ((y1 >= w_y && w_y >= y2)
		|| (y2 >= w_y && w_y >= y1))) {
	  if (abs(w_x - x1) < mindist) {
	    mindist = abs(w_x - x1);
	    min_x = x1;
	    min_y = w_y;
	  }
	}
	if ((y1 == y2)  /* horitontal net */
	    && ((x1 >= w_x && w_x >= x2)
		|| (x2 >= w_x && w_x >= x1))) {
	  if (abs(w_y - y1) < mindist) {
	    mindist = abs(w_y - y1);
	    min_x = w_x;
	    min_y = y1;
	  }
	}

	if (o_current->type == OBJ_BUS)
	  weight = mindist / MAGNETIC_BUS_WEIGHT;
	else /* OBJ_NET */
	  weight = mindist / MAGNETIC_NET_WEIGHT;
      }
      else { /* neither pin nor net or bus */
	continue;
      }

      if (o_magnetic == NULL
	  || weight < min_weight) {
	minbest = mindist;
	min_weight = weight;
	o_magnetic = o_current;
	w_current->magnetic_wx = min_x;
	w_current->magnetic_wy = min_y;
      }
    }
  }

  /* check whether we found an object and if it's close enough */
  if (o_magnetic != NULL) {
    switch (o_magnetic->type) {
    case (OBJ_PIN): magnetic_reach = MAGNETIC_PIN_REACH; break;
    case (OBJ_NET): magnetic_reach = MAGNETIC_NET_REACH; break;
    case (OBJ_BUS): magnetic_reach = MAGNETIC_BUS_REACH; break;
    }
    if (minbest > gschem_page_view_WORLDabs (page_view, magnetic_reach)) {
      w_current->magnetic_wx = -1;
      w_current->magnetic_wy = -1;
    }
  }
  else {
    w_current->magnetic_wx = -1;
    w_current->magnetic_wy = -1;
  }

  g_list_free (object_list);
}
Пример #5
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 *  \todo Only descends into the first source schematic
 *
 */
int o_edit_find_text (GSCHEM_TOPLEVEL *w_current, const GList *o_list,
                      char *stext, int descend, int skip)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  char *attrib = NULL;
  int count = 0;
  PAGE *parent = NULL;
  char *current_filename = NULL;
  int page_control = 0;
  int pcount = 0;
  int rv;
  int x1, y1, x2, y2;
  int text_screen_height;
  const GList *iter;

  OBJECT *o_current;

  skiplast = skip;

  iter = o_list;
  while (iter != NULL) {
    o_current = (OBJECT *)iter->data;

    if (descend) {
      if (o_current->type == OBJ_COMPLEX) {
        parent = toplevel->page_current;
        attrib = o_attrib_search_attached_attribs_by_name (o_current,
                                                           "source", count);

        /* if above is null, then look inside symbol */
        if (attrib == NULL) {
          attrib = o_attrib_search_inherited_attribs_by_name (o_current,
                                                              "source", count);
          /*          looking_inside = TRUE; */
        }

        if (attrib) {
          pcount = 0;
          current_filename = u_basic_breakup_string(attrib, ',', pcount);
          if (current_filename != NULL) {
            PAGE *child_page =
              s_hierarchy_down_schematic_single(toplevel,
                                                current_filename,
                                                parent,
                                                page_control,
                                                HIERARCHY_NORMAL_LOAD);

            if (child_page != NULL) {
              page_control = child_page->page_control;
              rv = o_edit_find_text (w_current,
                                     s_page_objects (child_page),
                                     stext, descend, skiplast);
              if (!rv) {
                s_page_goto( toplevel, child_page );
                return 0;
              }
            }
          }
        }
      }
    }

    if (o_current->type == OBJ_TEXT) {
      const gchar *str = o_text_get_string (toplevel, o_current);
     /* replaced strcmp with strstr to simplify the search */
      if (strstr (str,stext)) {
        if (!skiplast) {
          a_zoom(w_current, ZOOM_FULL, DONTCARE, A_PAN_DONT_REDRAW);
          world_get_single_object_bounds (toplevel, o_current, &x1, &y1, &x2, &y2);
          text_screen_height = SCREENabs (w_current, y2 - y1);
          /* this code will zoom/pan till the text screen height is about */
          /* 50 pixels high, perhaps a future enhancement will be to make */
          /* this number configurable */
          while (text_screen_height < 50) {
            a_zoom(w_current, ZOOM_IN, DONTCARE, A_PAN_DONT_REDRAW);
            text_screen_height = SCREENabs (w_current, y2 - y1);
          }
          a_pan_general(w_current,
                        o_current->text->x, o_current->text->y,
                        1, 0);

	  /* Make sure the titlebar and scrollbars are up-to-date */
	  x_window_set_current_page(w_current, 
                                    w_current->toplevel->page_current );

          last_o = o_current;
          break;
        }
        if (last_o == o_current) {
          skiplast = 0;
        }

      } /* if (strstr(o_current->text->string,stext)) */
    } /* if (o_current->type == OBJ_TEXT) */
    iter = g_list_next (iter);

    if (iter == NULL) {
      return 1;
    }
  }
  return (iter == NULL);
}
Пример #6
0
/*! \brief Get the object bounds of the given object, excluding the object
 *  types given as parameters.
 *  \par Function Description
 *  Get the object bounds without considering the attributes in
 *  exclude_attrib_list, neither the object types included in
 *  exclude_obj_type_list
 *  \param [in] toplevel TOPLEVEL structure.
 *  \param [in] o_current The object we want to know the bounds of.
 *  \param [in] exclude_attrib_list A list with the attribute names we don't
 *  want to include when calculing the bounds.
 *  \param [in] exclude_obj_type_list A list with the object types we don't
 *  want to include when calculing the bounds.
 *  The object types are those used in (OBJECT *)->type converted into strings.
 *  \param [out] left Left bound of the object.
 *  \param [out] top  Top bound of the object.
 *  \param [out] right Right bound of the object.
 *  \param [out] bottom  Bottom bound of the object.
 *
 */
static void custom_world_get_single_object_bounds
(TOPLEVEL *toplevel, OBJECT *o_current,
 int *left, int *top,
 int *right, int *bottom,
 GList *exclude_attrib_list,
 GList *exclude_obj_type_list) {
    OBJECT *obj_ptr = NULL;
    OBJECT *a_current;
    GList *a_iter;
    int rleft, rright, rbottom, rtop;
    const gchar *text_value;
    char *name_ptr, aux_ptr[2];
    gboolean include_text;

    *left = rleft = toplevel->init_right;
    *top = rtop = toplevel->init_bottom;;
    *right = *bottom = rright = rbottom = 0;

    obj_ptr = o_current;
    sprintf(aux_ptr, "%c", obj_ptr->type);
    include_text = TRUE;
    if (!g_list_find_custom(exclude_obj_type_list, aux_ptr,
                            (GCompareFunc) &strcmp)) {

        switch(obj_ptr->type) {
        case (OBJ_PIN):
            world_get_single_object_bounds (toplevel, obj_ptr,
                                            &rleft, &rtop, &rright, &rbottom);
            break;
        case (OBJ_TEXT):
            text_value = o_text_get_string (toplevel, obj_ptr);
            if (text_value) {
                if (o_attrib_get_name_value(text_value, &name_ptr, NULL) &&
                        g_list_find_custom(exclude_attrib_list, name_ptr, (GCompareFunc) &strcmp)) {
                    include_text = FALSE;
                }
                if (g_list_find_custom(exclude_attrib_list, "all",
                                       (GCompareFunc) &strcmp)) {
                    include_text = FALSE;
                }
                if (include_text) {
                    world_get_single_object_bounds (toplevel, obj_ptr,
                                                    &rleft, &rtop, &rright, &rbottom);
                }
                g_free(name_ptr);
            }
            break;
        case (OBJ_COMPLEX):
        case (OBJ_PLACEHOLDER):
            custom_world_get_object_glist_bounds (toplevel,
                                                  o_current->complex->prim_objs,
                                                  left, top, right, bottom,
                                                  exclude_attrib_list,
                                                  exclude_obj_type_list);
            break;

        default:
            world_get_single_object_bounds (toplevel, obj_ptr,
                                            &rleft, &rtop, &rright, &rbottom);
            break;
        }

        if (rleft < *left) *left = rleft;
        if (rtop < *top) *top = rtop;
        if (rright > *right) *right = rright;
        if (rbottom > *bottom) *bottom = rbottom;

        /* If it's a pin object, check the pin attributes */
        if (obj_ptr->type == OBJ_PIN) {
            a_iter = obj_ptr->attribs;
            while (a_iter != NULL) {
                a_current = a_iter->data;

                if (a_current->type == OBJ_TEXT) {
                    custom_world_get_single_object_bounds(toplevel,
                                                          a_current,
                                                          &rleft, &rtop,
                                                          &rright, &rbottom,
                                                          exclude_attrib_list,
                                                          exclude_obj_type_list);
                    if (rleft < *left) *left = rleft;
                    if (rtop < *top) *top = rtop;
                    if (rright > *right) *right = rright;
                    if (rbottom > *bottom) *bottom = rbottom;
                }

                a_iter = g_list_next (a_iter);
            }
        }
    }
}