Example #1
0
/*! \brief Rotate all objects in list.
 *  \par Function Description
 *  Given an object <B>list</B>, and the center of rotation
 *  (<B>centerx</B>,<B>centery</B>, this function traverses all the selection
 *  list, rotating each object through angle <B>angle</B>.
 *  The list contains a given object and all its attributes
 *  (refdes, pinname, pinlabel, ...).
 *  There is a second pass to run the rotate hooks of non-simple objects,
 *  like pin or complex objects, for example.
 *
 *  \param [in] w_current  The GschemToplevel object.
 *  \param [in] centerx    Center x coordinate of rotation.
 *  \param [in] centery    Center y coordinate of rotation.
 *  \param [in] angle      Angle to rotate the objects through.
 *  \param [in] list       The list of objects to rotate.
 */
void o_rotate_world_update(GschemToplevel *w_current,
                           int centerx, int centery, int angle, GList *list)
{
  TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
  OBJECT *o_current;
  GList *o_iter;

  /* this is okay if you just hit rotate and have nothing selected */
  if (list == NULL) {
    i_action_stop (w_current);
    i_set_state(w_current, SELECT);
    return;
  }

  o_invalidate_glist (w_current, list);

  /* Find connected objects, removing each object in turn from the
   * connection list. We only _really_ want those objects connected
   * to the selection, not those within in it.
   */
  for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
    o_current = o_iter->data;

    s_conn_remove_object_connections (toplevel, o_current);
  }

  o_glist_rotate_world( toplevel, centerx, centery, angle, list );

  /* Find connected objects, adding each object in turn back to the
   * connection list. We only _really_ want those objects connected
   * to the selection, not those within in it.
   */
  for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
    o_current = o_iter->data;

    s_conn_update_object (o_current->page, o_current);
  }

  o_invalidate_glist (w_current, list);

  /* Run rotate-objects-hook */
  g_run_hook_object_list (w_current, "%rotate-objects-hook", list);

  /* Don't save the undo state if we are inside an action */
  /* This is useful when rotating the selection while moving, for example */
  gschem_toplevel_page_content_changed (w_current, toplevel->page_current);
  if (!w_current->inside_action) {
    o_undo_savestate_old(w_current, UNDO_ALL);
  }

  if (w_current->event_state == ROTATEMODE) {
    i_set_state(w_current, SELECT);
  }
}
Example #2
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void o_mirror_world_update(GschemToplevel *w_current, int centerx, int centery, GList *list)
{
  TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
  OBJECT *o_current;
  GList *o_iter;

  if (list == NULL) {
    i_action_stop (w_current);
    i_set_state(w_current, SELECT);
    return;
  }

  o_invalidate_glist (w_current, list);

  /* Find connected objects, removing each object in turn from the
   * connection list. We only _really_ want those objects connected
   * to the selection, not those within in it.
   */
  for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
    o_current = o_iter->data;

    s_conn_remove_object_connections (toplevel, o_current);
  }

  o_glist_mirror_world( toplevel, centerx, centery, list );

  /* Find connected objects, adding each object in turn back to the
   * connection list. We only _really_ want those objects connected
   * to the selection, not those within in it.
   */
  for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
    o_current = o_iter->data;

    s_conn_update_object (o_current->page, o_current);
  }

  o_invalidate_glist (w_current, list);

  /* Run mirror-objects-hook */
  g_run_hook_object_list (w_current, "%mirror-objects-hook", list);

  gschem_toplevel_page_content_changed (w_current, toplevel->page_current);
  o_undo_savestate_old(w_current, UNDO_ALL);

  if (w_current->event_state == MIRRORMODE) {
    i_set_state(w_current, SELECT);
  }
}
Example #3
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void o_mirror_world_update(GSCHEM_TOPLEVEL *w_current, int centerx, int centery, GList *list)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  OBJECT *o_current;
  GList *o_iter;

  if (list == NULL) {
    w_current->inside_action = 0;
    i_set_state(w_current, SELECT);
    return;
  }

  o_invalidate_glist (w_current, list);

  /* Find connected objects, removing each object in turn from the
   * connection list. We only _really_ want those objects connected
   * to the selection, not those within in it.
   */
  for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
    o_current = o_iter->data;

    s_conn_remove_object (toplevel, o_current);
  }

  o_glist_mirror_world( toplevel, centerx, centery, list );

  /* Find connected objects, adding each object in turn back to the
   * connection list. We only _really_ want those objects connected
   * to the selection, not those within in it.
   */
  for (o_iter = list; o_iter != NULL; o_iter = g_list_next (o_iter)) {
    o_current = o_iter->data;

    s_conn_update_object (toplevel, o_current);
  }

  o_invalidate_glist (w_current, list);

  /* Run mirror-objects-hook */
  g_run_hook_object_list ("%mirror-objects-hook", list);

  toplevel->page_current->CHANGED=1;
  o_undo_savestate(w_current, UNDO_ALL);
}
Example #4
0
/*! \brief finish a bus drawing action
 *  \par Function Description
 *  This function finishes a net drawing action. The function draws
 *  a bus from the point (<B>first_wx</B>,<B>first_wy</B>) to
 *  (<B>second_wx</B>,<B>second_wy</B>). Both points are taken from
 *  the <B>GschemToplevel</B> structure.
 *
 *  The function returns TRUE if a bus object has been created and
 *  FALSE if no bus object has been created.
 *
 *  \param [in] w_current  The GschemToplevel object.
 *  \param [in] w_x        (unused)
 *  \param [in] w_y        (unused)
 */
void o_bus_end(GschemToplevel *w_current, int w_x, int w_y)
{
  OBJECT *new_obj;

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

  g_assert( w_current->inside_action != 0 );

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

  TOPLEVEL *toplevel = page->toplevel;
  g_return_if_fail (toplevel != NULL);

  GList *prev_conn_objects = NULL;

  /* erase the rubberbus */
  /* o_bus_invalidate_rubber (w_current); */
  w_current->rubber_visible = 0;

  /* don't allow zero length bus */
  /* this ends the bus drawing behavior we want this? hack */
  if ( (w_current->first_wx != w_current->second_wx) ||
       (w_current->first_wy != w_current->second_wy) ) {

    new_obj = geda_bus_object_new (toplevel,
                                   BUS_COLOR,
                                   w_current->first_wx,
                                   w_current->first_wy,
                                   w_current->second_wx,
                                   w_current->second_wy,
                                   0);
    s_page_append (toplevel, page, new_obj);

    /* connect the new bus to the other busses */
    prev_conn_objects = s_conn_return_others (prev_conn_objects, new_obj);
    o_invalidate_glist (w_current, prev_conn_objects);
    g_list_free (prev_conn_objects);

    /* Call add-objects-hook */
    g_run_hook_object (w_current, "%add-objects-hook", new_obj);

    w_current->first_wx = w_current->second_wx;
    w_current->first_wy = w_current->second_wy;

    gschem_toplevel_page_content_changed (w_current, page);
    o_undo_savestate(w_current, page, UNDO_ALL);
  }

  /* Don't reset w_current->inside_action here since we want to continue drawing */
}
Example #5
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void o_move_start(GschemToplevel *w_current, int w_x, int w_y)
{
  GList *s_iter;

  g_return_if_fail (w_current != NULL);

  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);

  g_return_if_fail (w_current->stretch_list == NULL);

  if (o_select_selected (w_current)) {
    i_set_state (w_current, MOVEMODE);

    gboolean net_rubber_band_mode;

    net_rubber_band_mode = gschem_options_get_net_rubber_band_mode (w_current->options);

    w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;

    w_current->first_wx = w_current->second_wx = w_x;
    w_current->first_wy = w_current->second_wy = w_y;

    o_invalidate_glist (w_current, geda_list_get_glist (page->selection_list));

    if (net_rubber_band_mode) {
      o_move_prep_rubberband(w_current);

      /* Set the dont_redraw flag on rubberbanded objects and invalidate them.
       * This ensures that they are not drawn (in their un-stretched position)
       * during screen updates. */
      for (s_iter = w_current->stretch_list;
           s_iter != NULL; s_iter = g_list_next (s_iter)) {
        STRETCH *stretch = s_iter->data;
        stretch->object->dont_redraw = TRUE;
        o_invalidate (w_current, stretch->object);
      }
    }

    o_select_move_to_place_list(w_current);
    i_action_start (w_current);

    o_move_invalidate_rubber (w_current, TRUE);
  }
}
Example #6
0
/*! \brief End placement action
 *
 *  \par Function Description
 *  This function finishes the current placement action by adding
 *  objects to the current page at the given new world coordinates
 *  and redrawing them on the canvas. It also saves the current
 *  state in the undo list and updates the menus.
 *
 *  If \a continue_placing is TRUE, a copy of the placement list
 *  is saved to start a new place action.
 *
 *  \param [in]  w_current  GschemToplevel which we're drawing for.
 *  \param [in]  w_x        The current world X coordinate.
 *  \param [in]  w_y        The current world Y coordinate.
 *  \param [in]  hook_name  The hook to run after adding the objects.
 */
void o_place_end (GschemToplevel *w_current,
                  int w_x, int w_y,
                  int continue_placing,
                  const char* hook_name)
{
  int w_diff_x, w_diff_y;
  OBJECT *o_current;
  GList *temp_dest_list = NULL;
  GList *connected_objects = NULL;
  GList *iter;

  g_return_if_fail (w_current != NULL);
  g_assert (w_current->inside_action != 0);

  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);

  /* erase old image */
  /* o_place_invalidate_rubber (w_current, FALSE); */
  w_current->rubber_visible = 0;

  /* Calc final object positions */
  w_current->second_wx = w_x;
  w_current->second_wy = w_y;

  w_diff_x = w_current->second_wx - w_current->first_wx;
  w_diff_y = w_current->second_wy - w_current->first_wy;

  if (continue_placing) {
    /* Make a copy of the place list if we want to keep it afterwards */
    temp_dest_list = o_glist_copy_all (page->toplevel,
                                       page->place_list,
                                       temp_dest_list);
  } else {
    /* Otherwise just take it */
    temp_dest_list = page->place_list;
    page->place_list = NULL;
  }

  geda_object_list_translate (temp_dest_list, w_diff_x, w_diff_y);

  /* Attach each item back onto the page's object list. Update object
   * connectivity and add the new objects to the selection list.*/
  for (iter = temp_dest_list; iter != NULL; iter = g_list_next (iter)) {
    o_current = (OBJECT*) iter->data;

    s_page_append (page->toplevel, page, o_current);

    /* Update object connectivity */
    s_conn_update_object (page, o_current);
    connected_objects = s_conn_return_others (connected_objects, o_current);
  }

  if (hook_name != NULL) {
    g_run_hook_object_list (w_current, hook_name, temp_dest_list);
  }

  o_invalidate_glist (w_current, connected_objects);
  g_list_free (connected_objects);
  connected_objects = NULL;

  gschem_toplevel_page_content_changed (w_current, page);
  o_invalidate_glist (w_current, temp_dest_list); /* only redraw new objects */
  g_list_free (temp_dest_list);

  o_undo_savestate_old (w_current, UNDO_ALL);
  i_update_menus (w_current);

  if (!continue_placing) {
    i_set_state(w_current, SELECT);
    i_action_stop (w_current);
  }
}
Example #7
0
/*! \brief finish a net drawing action 
 * \par Function Description 
 * This function finishes the drawing of a net. If we have a visible
 * magnetic marker, we use that instead of the current cursor
 * position.
 *
 * The rubber nets are removed, the nets and cues are drawn and the
 * net is added to the TOPLEVEL structure.  
 *
 * The function returns TRUE if it has drawn a net, FALSE otherwise.
 */
int o_net_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  int color;
  int primary_zero_length, secondary_zero_length;
  int found_primary_connection = FALSE;
  int save_wx, save_wy;

  GList *prev_conn_objects = NULL;
  OBJECT *new_net = NULL;

  g_assert( w_current->inside_action != 0 );

  o_net_invalidate_rubber (w_current);

  if (w_current->magnetic_wx != -1 && w_current->magnetic_wy != -1)
    o_net_finishmagnetic(w_current);

  w_current->rubber_visible = 0;

  /* See if either of the nets are zero length.  We'll only add */
  /* the non-zero ones */
  primary_zero_length = (w_current->first_wx == w_current->second_wx) &&
    (w_current->first_wy == w_current->second_wy);
 
  secondary_zero_length = (w_current->second_wx == w_current->third_wx) &&
      (w_current->second_wy == w_current->third_wy);

  /* If both nets are zero length... */
  /* this ends the net drawing behavior */
  if ( primary_zero_length && secondary_zero_length ) {
    return FALSE;
  }

  save_wx = w_current->third_wx;
  save_wy = w_current->third_wy;

  if (toplevel->override_net_color == -1) {
    color = NET_COLOR;
  } else {
    color = toplevel->override_net_color;
  }

  if (w_current->third_wx != snap_grid (w_current, w_current->third_wx)
      || w_current->third_wy != snap_grid (w_current, w_current->third_wy))
      s_log_message(_("Warning: Ending net at off grid coordinate\n"));

  if (!primary_zero_length ) {
  /* create primary net */
      new_net = o_net_new(toplevel, OBJ_NET, color,
                          w_current->first_wx, w_current->first_wy,
                          w_current->second_wx, w_current->second_wy);
      s_page_append (toplevel->page_current, new_net);

      /* conn stuff */
      /* LEAK CHECK 1 */
      prev_conn_objects = s_conn_return_others (prev_conn_objects, new_net);

      if (o_net_add_busrippers (w_current, new_net, prev_conn_objects)) {
        g_list_free (prev_conn_objects);
        prev_conn_objects = NULL;
        prev_conn_objects = s_conn_return_others (prev_conn_objects, new_net);
      }

#if DEBUG 
      printf("primary:\n"); 
      s_conn_print(new_net->conn_list);
#endif

      o_invalidate (w_current, new_net);

      o_invalidate_glist (w_current, prev_conn_objects);

      g_list_free (prev_conn_objects);
      prev_conn_objects = NULL;

      /* Go off and search for valid connection on this newly created net */
      found_primary_connection = s_conn_net_search(new_net, 1, 
                                                   new_net->conn_list);
      if (found_primary_connection)
      {
      	/* if a net connection is found, reset start point of next net */
	save_wx = w_current->second_wx;
	save_wy = w_current->second_wy;
      }

      /* you don't want to consolidate nets which are drawn non-ortho */
      if (toplevel->net_consolidate == TRUE && !w_current->CONTROLKEY) {
        /* CAUTION: Object list will change when nets are consolidated, don't
         *          keep pointers to other objects than new_net after this. */
        o_net_consolidate_segments(toplevel, new_net);
      }
  }


  /* If the second net is not zero length, add it as well */
  /* Also, a valid net connection from the primary net was not found */
  if (!secondary_zero_length && !found_primary_connection) {
      
      /* Add secondary net */
      new_net = o_net_new(toplevel, OBJ_NET, color,
                          w_current->second_wx, w_current->second_wy,
                          w_current->third_wx, w_current->third_wy);
      s_page_append (toplevel->page_current, new_net);

      /* conn stuff */
      /* LEAK CHECK 2 */
      prev_conn_objects = s_conn_return_others (prev_conn_objects, new_net);

      if (o_net_add_busrippers (w_current, new_net, prev_conn_objects)) {
        g_list_free (prev_conn_objects);
        prev_conn_objects = NULL;
        prev_conn_objects = s_conn_return_others (prev_conn_objects, new_net);
      }
#if DEBUG
      s_conn_print(new_net->conn_list);
#endif

      o_invalidate (w_current, new_net);

      o_invalidate_glist (w_current, prev_conn_objects);

      g_list_free (prev_conn_objects);
      prev_conn_objects = NULL;

      /* you don't want to consolidate nets which are drawn non-ortho */
      if (toplevel->net_consolidate == TRUE && !w_current->CONTROLKEY) {
        /* CAUTION: Object list will change when nets are consolidated, don't
         *          keep pointers to other objects than new_net after this. */
        o_net_consolidate_segments(toplevel, new_net);
      }
  }

  toplevel->page_current->CHANGED = 1;
  w_current->first_wx = save_wx;
  w_current->first_wy = save_wy;
  o_undo_savestate(w_current, UNDO_ALL);

  return (TRUE);
}
Example #8
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void o_place_end (GSCHEM_TOPLEVEL *w_current,
                  int w_x, int w_y,
                  int continue_placing,
                  GList **ret_new_objects,
                  const char* hook_name)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  int w_diff_x, w_diff_y;
  OBJECT *o_current;
  PAGE *p_current;
  GList *temp_dest_list = NULL;
  GList *connected_objects = NULL;
  GList *iter;

  /* erase old image */
  /* o_place_invaidate_rubber (w_current, FALSE); */
  w_current->rubber_visible = 0;

  /* Calc final object positions */
  w_current->second_wx = w_x;
  w_current->second_wy = w_y;

  w_diff_x = w_current->second_wx - w_current->first_wx;
  w_diff_y = w_current->second_wy - w_current->first_wy;

  if (continue_placing) {
    /* Make a copy of the place list if we want to keep it afterwards */
    temp_dest_list = o_glist_copy_all (toplevel,
                                       toplevel->page_current->place_list,
                                       temp_dest_list);
  } else {
    /* Otherwise just take it */
    temp_dest_list = toplevel->page_current->place_list;
    toplevel->page_current->place_list = NULL;
  }

  if (ret_new_objects != NULL) {
    *ret_new_objects = g_list_copy (temp_dest_list);
  }

  o_glist_translate_world(toplevel, w_diff_x, w_diff_y, temp_dest_list);

  /* Attach each item back onto the page's object list. Update object
   * connectivity and add the new objects to the selection list.*/
  p_current = toplevel->page_current;

  for (iter = temp_dest_list; iter != NULL; iter = g_list_next (iter)) {
    o_current = iter->data;

    s_page_append (toplevel, p_current, o_current);

    /* Update object connectivity */
    s_conn_update_object (toplevel, o_current);
    connected_objects = s_conn_return_others (connected_objects, o_current);
  }

  if (hook_name != NULL) {
    g_run_hook_object_list (hook_name, temp_dest_list);
  }

  o_invalidate_glist (w_current, connected_objects);
  g_list_free (connected_objects);
  connected_objects = NULL;

  toplevel->page_current->CHANGED = 1;
  o_invalidate_glist (w_current, temp_dest_list); /* only redraw new objects */
  g_list_free (temp_dest_list);

  o_undo_savestate (w_current, UNDO_ALL);
  i_update_menus (w_current);
}
Example #9
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void o_move_end(GschemToplevel *w_current)
{
  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);

  GList *s_current = NULL;
  OBJECT *object;
  int diff_x, diff_y;
  GList *s_iter;
  GList *rubbernet_objects = NULL;
  gboolean net_rubber_band_mode;

  g_return_if_fail (w_current != NULL);
  g_return_if_fail (page != NULL);

  g_assert (w_current->inside_action != 0);

  object = o_select_return_first_object(w_current);

  if (!object) {
    /* actually this is an error condition hack */
    i_action_stop (w_current);
    i_set_state(w_current, SELECT);
    return;
  }

  diff_x = w_current->second_wx - w_current->first_wx;
  diff_y = w_current->second_wy - w_current->first_wy;

  o_move_invalidate_rubber (w_current, FALSE);
  w_current->rubber_visible = 0;

  net_rubber_band_mode = gschem_options_get_net_rubber_band_mode (w_current->options);

  if (net_rubber_band_mode) {
    o_move_end_rubberband (w_current, diff_x, diff_y, &rubbernet_objects);
  }

  /* Unset the dont_redraw flag on rubberbanded objects.
   * We set this above, in o_move_start(). */
  for (s_iter = w_current->stretch_list;
       s_iter != NULL; s_iter = g_list_next (s_iter)) {
    STRETCH *stretch = s_iter->data;
    stretch->object->dont_redraw = FALSE;
  }

  s_current = geda_list_get_glist( page->selection_list );

  while (s_current != NULL) {

    object = (OBJECT *) s_current->data;

    if (object == NULL) {
      fprintf(stderr, _("ERROR: NULL object in o_move_end!\n"));
      exit(-1);
    }


    switch (object->type) {
      case (OBJ_COMPLEX):
      case (OBJ_PLACEHOLDER):

        /* TODO: Fix so we can just pass the complex to o_move_end_lowlevel,
         * IE.. by falling through the bottom of this case statement. */

        /* this next section of code is from */
        /* o_complex_world_translate_world */
        object->complex->x = object->complex->x + diff_x;
        object->complex->y = object->complex->y + diff_y;

        o_move_end_lowlevel_glist (w_current, object->complex->prim_objs,
                                   diff_x, diff_y);
        object->w_bounds_valid_for = NULL;
        break;

      default:
        o_move_end_lowlevel (w_current, object, diff_x, diff_y);
        break;
    }

    s_current = g_list_next(s_current);
  }

  /* Draw the objects that were moved */
  o_invalidate_glist (w_current, geda_list_get_glist (page->selection_list));

  /* Draw the connected nets/buses that were also changed */
  o_invalidate_glist (w_current, rubbernet_objects);

  /* Call move-objects-hook for moved objects and changed connected
   * nets/buses */
  GList *moved_list = g_list_concat (page->place_list, rubbernet_objects);
  page->place_list = NULL;
  rubbernet_objects = NULL;
  g_run_hook_object_list (w_current, "%move-objects-hook", moved_list);
  g_list_free (moved_list);

  gschem_toplevel_page_content_changed (w_current, page);
  o_undo_savestate_old(w_current, UNDO_ALL);

  s_stretch_destroy_all (w_current->stretch_list);
  w_current->stretch_list = NULL;

  i_set_state(w_current, SELECT);
  i_action_stop (w_current);
}