Beispiel #1
0
/* This locks the entire selected list.  It does lock components, but does NOT
 * change the color (of primatives of the components) though
 * this cannot be called recursively */
void o_lock(GSCHEM_TOPLEVEL *w_current)
{
  OBJECT *object = NULL;
  GList *s_current = NULL;

  /* skip over head */
  s_current = geda_list_get_glist( w_current->toplevel->page_current->selection_list );

  while(s_current != NULL) {
    object = (OBJECT *) s_current->data;
    if (object) {
      /* check to see if locked_color is already being used */
      if (object->locked_color == -1) {
        object->selectable = FALSE;
        object->locked_color = object->color;
        object->color = LOCK_COLOR;
        w_current->toplevel->page_current->CHANGED=1;
      } else {
        s_log_message(_("Object already locked\n"));
      }
    }

    s_current = g_list_next(s_current);
  }

  if (!w_current->SHIFTKEY) o_select_unselect_all(w_current);
  o_undo_savestate(w_current, UNDO_ALL);
  i_update_menus(w_current);
}
Beispiel #2
0
/* \brief Callback for handling system clipboard owner change.
 * \par Function Description
 *
 */
static void
clip_handle_owner_change (GtkClipboard *cb, GdkEvent *event,
                          gpointer user_data)
{
  GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *) user_data;

  i_update_menus (w_current);
}
Beispiel #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 so,
 *  processes selection changes as appropriate for the object and passed
 *  flag. Saves a pointer to the found object so future find operations
 *  resume after this object.
 *
 *  \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.
 *  \param [in] change_selection  Whether to select the found object or not.
 *  \returns TRUE if the OBJECT was hit, otherwise FALSE.
 */
static gboolean
find_single_object (GschemToplevel *w_current, OBJECT *object,
                    int w_x, int w_y, int w_slack,
                    int change_selection)
{
  if (!is_object_hit (w_current, object, w_x, w_y, w_slack))
    return FALSE;

  if (change_selection) {
    /* FIXME: should this be moved to o_select_object()? (Werner) */
    if (object->type == OBJ_NET && w_current->net_selection_mode)
      o_select_connected_nets (w_current, object);
    else
      o_select_object (w_current, object, SINGLE, 0); /* 0 is count */
  }

  w_current->toplevel->page_current->object_lastplace = object;
  i_update_menus (w_current);
  return TRUE;
}
Beispiel #4
0
/*! \brief Changes the current page.
 *  \par Function Description
 *  This function displays the specified page <B>page</B> in the
 *  window attached to <B>toplevel</B>.
 *
 *  It changes the <B>toplevel</B>'s current page to <B>page</B>,
 *  draws it and updates the user interface.
 *
 *  <B>page</B> has to be in the list of PAGEs attached to <B>toplevel</B>.
 *
 *  \param [in] w_current The toplevel environment.
 *  \param [in] page      The page to become current page.
 */
void
x_window_set_current_page (GschemToplevel *w_current, PAGE *page)
{
  GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current);

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

  o_redraw_cleanstates (w_current);

  gschem_page_view_set_page (page_view, page);

  i_update_menus (w_current);
  i_set_filename (w_current, page->page_filename);

  x_pagesel_update (w_current);
  x_multiattrib_update (w_current);

  gschem_page_view_update_scroll_adjustments (page_view);
  gschem_page_view_invalidate_all (page_view);
}
Beispiel #5
0
/*! \brief Changes the current page.
 *  \par Function Description
 *  This function displays the specified page <B>page</B> in the
 *  window attached to <B>toplevel</B>.
 *
 *  It changes the <B>toplevel</B>'s current page to <B>page</B>,
 *  draws it and updates the user interface.
 *
 *  <B>page</B> has to be in the list of PAGEs attached to <B>toplevel</B>.
 *
 *  \param [in] w_current The toplevel environment.
 *  \param [in] page      The page to become current page.
 */
void
x_window_set_current_page (GSCHEM_TOPLEVEL *w_current, PAGE *page)
{
  TOPLEVEL *toplevel = w_current->toplevel;

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

  o_redraw_cleanstates (w_current);

  s_page_goto (toplevel, page);

  i_update_menus (w_current);
  i_set_filename (w_current, page->page_filename);

  x_pagesel_update (w_current);
  x_multiattrib_update (w_current);

  x_manual_resize (w_current);
  x_hscrollbar_update (w_current);
  x_vscrollbar_update (w_current);

  o_invalidate_all (w_current);
}
Beispiel #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);
  }
}
Beispiel #7
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
gint
x_event_button_pressed(GschemPageView *page_view, GdkEventButton *event, GschemToplevel *w_current)
{
  PAGE *page = gschem_page_view_get_page (page_view);
  int w_x, w_y;
  int unsnapped_wx, unsnapped_wy;

  g_return_val_if_fail ((w_current != NULL), 0);

  if (page == NULL) {
    return TRUE; /* terminate event */
  }

  if (!gtk_widget_has_focus (GTK_WIDGET (page_view))) {
    gtk_widget_grab_focus (GTK_WIDGET (page_view));
  }

  scm_dynwind_begin ((scm_t_dynwind_flags) 0);
  g_dynwind_window (w_current);

#if DEBUG
  printf("pressed button %d! \n", event->button);
  printf("event state: %d \n", event->state);
  printf("w_current state: %d \n", w_current->event_state);
  printf("Selection is:\n");
  o_selection_print_all(&(page->selection_list));
  printf("\n");
#endif

  gschem_page_view_SCREENtoWORLD (page_view, (int) event->x, (int) event->y,
                                  &unsnapped_wx, &unsnapped_wy);
  w_x = snap_grid (w_current, unsnapped_wx);
  w_y = snap_grid (w_current, unsnapped_wy);

  if (event->type == GDK_2BUTTON_PRESS &&
      w_current->event_state == SELECT) {
    /* Don't re-select an object (lp-912978) */
    /* o_find_object(w_current, w_x, w_y, TRUE); */

    /* GDK_BUTTON_EVENT is emitted before GDK_2BUTTON_EVENT, which
     * leads to setting of the inside_action flag.  If o_edit()
     * brings up a modal window (e.g., the edit attribute dialog),
     * it intercepts the release button event and thus doesn't
     * allow resetting of the inside_action flag so we do it
     * manually here before processing the double-click event. */
    i_action_stop (w_current);
    o_edit(w_current, geda_list_get_glist( page->selection_list ));
    scm_dynwind_end ();
    return(0);
  }

  w_current->SHIFTKEY   = (event->state & GDK_SHIFT_MASK  ) ? 1 : 0;
  w_current->CONTROLKEY = (event->state & GDK_CONTROL_MASK) ? 1 : 0;
  w_current->ALTKEY     = (event->state & GDK_MOD1_MASK) ? 1 : 0;

  /* Huge switch statement to evaluate state transitions. Jump to
   * end_button_pressed label to escape the state evaluation rather than
   * returning from the function directly. */

  if (event->button == 1) {
    if (w_current->inside_action) {
      /* End action */
      if (page->place_list != NULL) {
        switch(w_current->event_state) {
          case (COMPMODE)   : o_place_end(w_current, w_x, w_y, w_current->continue_component_place,
                                "%add-objects-hook"); break;
          case (TEXTMODE)   : o_place_end(w_current, w_x, w_y, FALSE,
                                "%add-objects-hook"); break;
          case (PASTEMODE)  : o_place_end(w_current, w_x, w_y, FALSE,
                                "%paste-objects-hook"); break;
          default: break;
        }
      } else {
        switch(w_current->event_state) {
          case (ARCMODE)    : o_arc_end1(w_current, w_x, w_y); break;
          case (BOXMODE)    : o_box_end(w_current, w_x, w_y); break;
          case (BUSMODE)    : o_bus_end(w_current, w_x, w_y); break;
          case (CIRCLEMODE) : o_circle_end(w_current, w_x, w_y); break;
          case (LINEMODE)   : o_line_end(w_current, w_x, w_y); break;
          case (NETMODE)    : o_net_end(w_current, w_x, w_y); break;
          case (PATHMODE)   : o_path_continue (w_current, w_x, w_y); break;
          case (PICTUREMODE): o_picture_end(w_current, w_x, w_y); break;
          case (PINMODE)    : o_pin_end (w_current, w_x, w_y); break;
          default: break;
        }
      }
    } else {
      /* Start action */
      switch(w_current->event_state) {
        case (ARCMODE)    : o_arc_start(w_current, w_x, w_y); break;
        case (BOXMODE)    : o_box_start(w_current, w_x, w_y); break;
        case (BUSMODE)    : o_bus_start(w_current, w_x, w_y); break;
        case (CIRCLEMODE) : o_circle_start(w_current, w_x, w_y); break;
        case (LINEMODE)   : o_line_start(w_current, w_x, w_y); break;
        case (NETMODE)    : o_net_start(w_current, w_x, w_y); break;
        case (PATHMODE)   : o_path_start (w_current, w_x, w_y); break;
        case (PICTUREMODE): o_picture_start(w_current, w_x, w_y); break;
        case (PINMODE)    : o_pin_start (w_current, w_x, w_y); break;
        case (ZOOMBOX)    : a_zoom_box_start(w_current, unsnapped_wx, unsnapped_wy); break;
        case (SELECT)     : o_select_start(w_current, w_x, w_y); break;

        case (COPYMODE)   :
        case (MCOPYMODE)  : o_copy_start(w_current, w_x, w_y); break;
        case (MOVEMODE)   : o_move_start(w_current, w_x, w_y); break;
        default: break;
      }
    }

    switch(w_current->event_state) {
      case(ROTATEMODE):   o_rotate_world_update(w_current, w_x, w_y, 90,
                            geda_list_get_glist(page->selection_list)); break;
      case(MIRRORMODE):   o_mirror_world_update(w_current, w_x, w_y,
                            geda_list_get_glist(page->selection_list)); break;

      case(PAN):
        gschem_page_view_pan (page_view, w_x, w_y);
        i_set_state(w_current, SELECT);
        break;
    }
  } else if (event->button == 2) {

    /* try this out and see how it behaves */
    if (w_current->inside_action) {
      if (!(w_current->event_state == COMPMODE||
            w_current->event_state == TEXTMODE||
            w_current->event_state == MOVEMODE||
            w_current->event_state == COPYMODE  ||
            w_current->event_state == MCOPYMODE ||
            w_current->event_state == PASTEMODE )) {
        i_callback_cancel(w_current, 0, NULL);
      }
      goto end_button_pressed;
    }

    switch(w_current->middle_button) {

      case(ACTION):

      /* don't want to search if shift */
      /* key is pressed */
      if (!w_current->SHIFTKEY) {
        o_find_object(w_current, unsnapped_wx, unsnapped_wy, TRUE);
      }

      /* make sure the list is not empty */
      if (!o_select_selected(w_current)) {
        /* this means the above find did not
         * find anything */
        i_action_stop (w_current);
        i_set_state(w_current, SELECT);
        goto end_button_pressed;
      }

      /* determine here if copy or move */
      if (w_current->ALTKEY) {
        i_set_state(w_current, COPYMODE);
        o_copy_start(w_current, w_x, w_y);
      } else {
        o_move_start(w_current, w_x, w_y);
      }
      break;

      case(REPEAT):
      if (w_current->last_callback != NULL) {
        (*w_current->last_callback)(w_current, 0, NULL);
      }
      break;
#ifdef HAVE_LIBSTROKE
      case(STROKE):
      DOING_STROKE=TRUE;
      break;
#endif /* HAVE_LIBSTROKE */

      case(MID_MOUSEPAN_ENABLED):
      gschem_page_view_pan_start (page_view, (int) event->x, (int) event->y);
      break;
    }

  } else if (event->button == 3) {
    if (!w_current->inside_action) {
      if (w_current->third_button == POPUP_ENABLED) {
        /* (third-button "popup") */
        i_update_menus(w_current);  /* update menus before popup  */
        do_popup(w_current, event);
      } else {
        /* (third-button "mousepan") */
        gschem_page_view_pan_start (page_view, (int) event->x, (int) event->y);
      }
    } else {
      if ((w_current->third_button == MOUSEPAN_ENABLED) &&
          (!w_current->third_button_cancel)) {
        gschem_page_view_pan_start (page_view, (int) event->x, (int) event->y);
      } else { /* this is the default cancel */

        /* reset all draw and place actions */

        switch (w_current->event_state) {

          case (ARCMODE)    : o_arc_invalidate_rubber     (w_current); break;
          case (BOXMODE)    : o_box_invalidate_rubber     (w_current); break;
          case (BUSMODE)    : o_bus_invalidate_rubber     (w_current); break;
          case (CIRCLEMODE) : o_circle_invalidate_rubber  (w_current); break;
          case (LINEMODE)   : o_line_invalidate_rubber    (w_current); break;
          case (NETMODE)    : o_net_reset                 (w_current); break;
          case (PATHMODE)   : o_path_invalidate_rubber    (w_current); break;
          case (PICTUREMODE): o_picture_invalidate_rubber (w_current); break;
          case (PINMODE)    : o_pin_invalidate_rubber     (w_current); break;

          default:
            i_callback_cancel(w_current, 0, NULL);
            break;
        }
      }
    }
  }

 end_button_pressed:
  scm_dynwind_end ();

  return(0);
}
Beispiel #8
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 *  <B>type</B> can be one of the following values:
 *  <DL>
 *    <DT>*</DT><DD>UNDO_ACTION
 *    <DT>*</DT><DD>REDO_ACTION
 *  </DL>
 */
void
o_undo_callback (GschemToplevel *w_current, PAGE *page, int type)
{
  TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
  UNDO *u_current;
  UNDO *u_next;
  UNDO *save_bottom;
  UNDO *save_tos;
  UNDO *save_current;
  int save_logging;
  int find_prev_data=FALSE;

  char *save_filename;

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

  if (w_current->undo_control == FALSE) {
    s_log_message(_("Undo/Redo disabled in rc file\n"));
    return;
  }

  if (page->undo_current == NULL) {
    return;
  }

  if (type == UNDO_ACTION) {
    u_current = page->undo_current->prev;
  } else {
    u_current = page->undo_current->next;
  }

  u_next = page->undo_current;

  if (u_current == NULL) {
    return;
  }

  if (u_next->type == UNDO_ALL && u_current->type == UNDO_VIEWPORT_ONLY) {
#if DEBUG
    printf("Type: %d\n", u_current->type);
    printf("Current is an undo all, next is viewport only!\n");
#endif
    find_prev_data = TRUE;

    if (w_current->undo_type == UNDO_DISK) {
      u_current->filename = o_undo_find_prev_filename(u_current);
    } else {
      u_current->object_list = o_undo_find_prev_object_head (u_current);
    }
  }

  /* save filename */
  save_filename = g_strdup (page->page_filename);

  /* save structure so it's not nuked */
  save_bottom = page->undo_bottom;
  save_tos = page->undo_tos;
  save_current = page->undo_current;
  page->undo_bottom = NULL;
  page->undo_tos = NULL;
  page->undo_current = NULL;

  o_select_unselect_all (w_current);

  if (w_current->undo_type == UNDO_DISK && u_current->filename) {
    /* delete objects of page */
    s_page_delete_objects (toplevel, page);

    /* Free the objects in the place list. */
    geda_object_list_delete (toplevel, page->place_list);
    page->place_list = NULL;

    gschem_toplevel_page_content_changed (w_current, page);
  } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) {
    /* delete objects of page */
    s_page_delete_objects (toplevel, page);

    /* Free the objects in the place list. */
    geda_object_list_delete (toplevel, page->place_list);
    page->place_list = NULL;

    gschem_toplevel_page_content_changed (w_current, page);
  }


  /* temporarily disable logging */
  save_logging = do_logging;
  do_logging = FALSE;

  if (w_current->undo_type == UNDO_DISK && u_current->filename) {

    f_open(toplevel, page, u_current->filename, NULL);

  } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) {

    s_page_append_list (toplevel, page,
                        o_glist_copy_all (toplevel, u_current->object_list,
                                          NULL));
  }

  page->page_control = u_current->page_control;
  page->up = u_current->up;
  gschem_toplevel_page_content_changed (w_current, page);

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

  GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (view);

  if (u_current->scale != 0) {
    gschem_page_geometry_set_viewport (geometry,
                                       u_current->x,
                                       u_current->y,
                                       u_current->scale);
    gschem_page_view_invalidate_all (view);
  } else {
    gschem_page_view_zoom_extents (view, u_current->object_list);
  }

  /* restore logging */
  do_logging = save_logging;

  /* set filename right */
  g_free(page->page_filename);
  page->page_filename = save_filename;

  /* final redraw */
  x_pagesel_update (w_current);
  x_multiattrib_update (w_current);
  i_update_menus(w_current);

  /* restore saved undo structures */
  page->undo_bottom = save_bottom;
  page->undo_tos = save_tos;
  page->undo_current = save_current;

  if (type == UNDO_ACTION) {
    if (page->undo_current) {
      page->undo_current = page->undo_current->prev;
      if (page->undo_current == NULL) {
        page->undo_current = page->undo_bottom;
      }
    }
  } else { /* type is REDO_ACTION */
    if (page->undo_current) {
      page->undo_current = page->undo_current->next;
      if (page->undo_current == NULL) {
        page->undo_current = page->undo_tos;
      }
    }
  }

  /* don't have to free data here since filename, object_list are */
  /* just pointers to the real data (lower in the stack) */
  if (find_prev_data) {
    u_current->filename = NULL;
    u_current->object_list = NULL;
  }

#if DEBUG
  printf("\n\n---Undo----\n");
  s_undo_print_all(page->undo_bottom);
  printf("TOS: %s\n", page->undo_tos->filename);
  printf("CURRENT: %s\n", page->undo_current->filename);
  printf("----\n");
#endif
}
Beispiel #9
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 *  <B>type</B> can be one of the following values:
 *  <DL>
 *    <DT>*</DT><DD>UNDO_ACTION
 *    <DT>*</DT><DD>REDO_ACTION
 *  </DL>
 */
void o_undo_callback(GSCHEM_TOPLEVEL *w_current, int type)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  UNDO *u_current;
  UNDO *u_next;
  UNDO *save_bottom;
  UNDO *save_tos;
  UNDO *save_current;
  int save_logging;
  int find_prev_data=FALSE;

  char *save_filename;

  if (w_current->undo_control == FALSE) {
    s_log_message(_("Undo/Redo disabled in rc file\n"));
    return;
  }

  if (toplevel->page_current->undo_current == NULL) {
    return;
  }

  if (type == UNDO_ACTION) {
    u_current = toplevel->page_current->undo_current->prev;
  } else {
    u_current = toplevel->page_current->undo_current->next;
  }

  u_next = toplevel->page_current->undo_current;

  if (u_current == NULL) {
    return;
  }

  if (u_next->type == UNDO_ALL && u_current->type == UNDO_VIEWPORT_ONLY) {
#if DEBUG
    printf("Type: %d\n", u_current->type);
    printf("Current is an undo all, next is viewport only!\n");
#endif
    find_prev_data = TRUE;

    if (w_current->undo_type == UNDO_DISK) {
      u_current->filename = o_undo_find_prev_filename(u_current);
    } else {
      u_current->object_list = o_undo_find_prev_object_head (u_current);
    }
  }

  /* save filename */
  save_filename = g_strdup (toplevel->page_current->page_filename);

  /* save structure so it's not nuked */
  save_bottom = toplevel->page_current->undo_bottom;
  save_tos = toplevel->page_current->undo_tos;
  save_current = toplevel->page_current->undo_current;
  toplevel->page_current->undo_bottom = NULL;
  toplevel->page_current->undo_tos = NULL;
  toplevel->page_current->undo_current = NULL;

  if (w_current->undo_type == UNDO_DISK && u_current->filename) {
    PAGE *p_new;
    s_page_delete (toplevel, toplevel->page_current);
    p_new = s_page_new(toplevel, u_current->filename);
    s_page_goto (toplevel, p_new);
  } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) {
    PAGE *p_new;
    s_page_delete (toplevel, toplevel->page_current);
    p_new = s_page_new (toplevel, save_filename);
    s_page_goto (toplevel, p_new);
  }

  /* temporarily disable logging */
  save_logging = do_logging;
  do_logging = FALSE;

  if (w_current->undo_type == UNDO_DISK && u_current->filename) {

    f_open(toplevel, toplevel->page_current, u_current->filename, NULL);

    x_manual_resize(w_current);
    toplevel->page_current->page_control = u_current->page_control;
    toplevel->page_current->up = u_current->up;
    toplevel->page_current->CHANGED=1;

  } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) {

    s_page_delete_objects (toplevel, toplevel->page_current);

    s_page_append_list (toplevel, toplevel->page_current,
                        o_glist_copy_all (toplevel, u_current->object_list,
                                          NULL));

    x_manual_resize(w_current);
    toplevel->page_current->page_control = u_current->page_control;
    toplevel->page_current->up = u_current->up;
    toplevel->page_current->CHANGED=1;
  }

  /* do misc setups */
  set_window(toplevel, toplevel->page_current,
             u_current->left, u_current->right,
             u_current->top, u_current->bottom);
  x_hscrollbar_update(w_current);
  x_vscrollbar_update(w_current);

  /* restore logging */
  do_logging = save_logging;

  /* set filename right */
  g_free(toplevel->page_current->page_filename);
  toplevel->page_current->page_filename = save_filename;

  /* final redraw */
  x_pagesel_update (w_current);
  x_multiattrib_update (w_current);

  /* Let the caller to decide if redraw or not */
  o_invalidate_all (w_current);
  i_update_menus(w_current);

  /* restore saved undo structures */
  toplevel->page_current->undo_bottom = save_bottom;
  toplevel->page_current->undo_tos = save_tos;
  toplevel->page_current->undo_current = save_current;

  if (type == UNDO_ACTION) {
    if (toplevel->page_current->undo_current) {
      toplevel->page_current->undo_current =
          toplevel->page_current->undo_current->prev;
      if (toplevel->page_current->undo_current == NULL) {
        toplevel->page_current->undo_current =
            toplevel->page_current->undo_bottom;
      }
    }
  } else { /* type is REDO_ACTION */
    if (toplevel->page_current->undo_current) {
      toplevel->page_current->undo_current =
          toplevel->page_current->undo_current->next;
      if (toplevel->page_current->undo_current == NULL) {
        toplevel->page_current->undo_current =
            toplevel->page_current->undo_tos;
      }
    }
  }

  /* don't have to free data here since filename, object_list are */
  /* just pointers to the real data (lower in the stack) */
  if (find_prev_data) {
    u_current->filename = NULL;
    u_current->object_list = NULL;
  }

#if DEBUG
  printf("\n\n---Undo----\n");
  s_undo_print_all(toplevel->page_current->undo_bottom);
  printf("TOS: %s\n", toplevel->page_current->undo_tos->filename);
  printf("CURRENT: %s\n", toplevel->page_current->undo_current->filename);
  printf("----\n");
#endif
}
Beispiel #10
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);
}
Beispiel #11
0
/*! \brief Find an OBJECT at a given set of coordinates
 *
 *  \par Function Description
 *  Tests for OBJECTS hit at a given set of coordinates. If
 *  change_selection is TRUE, it updates the page's selection.
 *
 *  Find operations resume searching after the last object which was
 *  found, so multiple find operations at the same point will cycle
 *  through any objects on top of each other at this location.
 *
 *  \param [in] w_current         The GschemToplevel object.
 *  \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] change_selection  Whether to select the found object or not.
 *  \returns TRUE if the object was hit at the given coordinates,
 *           otherwise FALSE.
 */
gboolean o_find_object (GschemToplevel *w_current, int w_x, int w_y,
                        gboolean change_selection)
{
  GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current);
  g_return_val_if_fail (page_view != NULL, FALSE);

  TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
  g_return_val_if_fail (toplevel != NULL, FALSE);

  int w_slack;
  const GList *iter = NULL;

  w_slack = gschem_page_view_WORLDabs (page_view, w_current->select_slack_pixels);

  /* Decide whether to iterate over all object or start at the last
     found object. If there is more than one object below the
     (w_x/w_y) position, this will select the next object below the
     position point. You can change the selected object by clicking
     at the same place multiple times. */
  if (toplevel->page_current->object_lastplace != NULL) {
    /* NB: g_list_find doesn't declare its input const, so we cast */
    iter = g_list_find ((GList *)s_page_objects (toplevel->page_current),
                        toplevel->page_current->object_lastplace);
    iter = g_list_next (iter);
  }

  /* do first search (if we found any objects after the last found object) */
  while (iter != NULL) {
    OBJECT *o_current = iter->data;
    if (find_single_object (w_current, o_current,
                            w_x, w_y, w_slack, change_selection)) {
      return TRUE;
    }
    iter = g_list_next (iter);
  }

  /* now search from the beginning up until the object_lastplace */
  for (iter = s_page_objects (toplevel->page_current);
       iter != NULL; iter = g_list_next (iter)) {
    OBJECT *o_current = iter->data;
    if (find_single_object (w_current, o_current,
                            w_x, w_y, w_slack, change_selection)) {
      return TRUE;
    }
    /* break once we've inspected up to where we started the first loop */
    if (o_current == toplevel->page_current->object_lastplace)
      break;
  }

  /* didn't find anything.... reset lastplace */
  toplevel->page_current->object_lastplace = NULL;

  /* deselect everything only if shift key isn't pressed and
     the caller allows it */
  if (change_selection && (!w_current->SHIFTKEY)) {
    o_select_unselect_all (w_current);
  }

  i_update_menus(w_current);
  return FALSE;
}
Beispiel #12
0
/*! \brief Delete objects from the selection.
 *  \par Function Description
 *  This function deletes the objects selected on the current page of
 *  toplevel \a w_current.
 *
 *  \param [in] w_current The GschemToplevel object.
 */
void o_delete_selected (GschemToplevel *w_current)
{
    TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
    SELECTION *selection = toplevel->page_current->selection_list;
    GList *to_remove;
    GList *iter;
    OBJECT *obj;
    unsigned int locked_num = 0;

    g_return_if_fail (o_select_selected (w_current));

    to_remove = g_list_copy (geda_list_get_glist (selection));

    for (iter = to_remove; iter != NULL; iter = g_list_next (iter)) {
        obj = (OBJECT *) iter->data;
        if (obj->selectable == FALSE)
            locked_num++;
    }

    if (locked_num > 0) {
        GList *non_locked = NULL;
        gint resp;
        GtkWidget *dialog = gtk_message_dialog_new (NULL,
                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                            GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
                            ngettext ("Delete locked object?", "Delete %u locked objects?",
                                      locked_num), locked_num);
        gtk_dialog_add_buttons (GTK_DIALOG (dialog),
                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                GTK_STOCK_YES, GTK_RESPONSE_YES,
                                GTK_STOCK_NO, GTK_RESPONSE_NO, NULL);
        gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO);

        resp = gtk_dialog_run (GTK_DIALOG (dialog));
        gtk_widget_destroy (dialog);

        switch (resp) {
        case GTK_RESPONSE_YES:  /* Remove all */
            break;
        case GTK_RESPONSE_NO:   /* Remove non locked */
            for (iter = to_remove; iter != NULL; iter = g_list_next (iter)) {
                obj = (OBJECT *) iter->data;
                if (obj->selectable == TRUE)
                    non_locked = g_list_append (non_locked, iter->data);
            }
            g_list_free (to_remove);
            to_remove = non_locked;
            break;
        default:                /* Cancel */
            g_list_free (to_remove);
            return;
        }
    }

    for (iter = to_remove; iter != NULL; iter = g_list_next (iter)) {
        obj = (OBJECT *) iter->data;
        o_selection_remove (toplevel, selection, obj);
        s_page_remove (toplevel, toplevel->page_current, obj);
    }

    g_run_hook_object_list (w_current, "%remove-objects-hook", to_remove);

    for (iter = to_remove; iter != NULL; iter = g_list_next (iter)) {
        obj = (OBJECT *) iter->data;
        s_delete_object (toplevel, obj);
    }

    g_list_free (to_remove);

    gschem_toplevel_page_content_changed (w_current, toplevel->page_current);
    w_current->inside_action = 0;
    o_undo_savestate_old (w_current, UNDO_ALL);
    i_update_menus (w_current);
}