Exemple #1
0
/*! \brief Records a new point for the stroke.
 *  \par Function Description
 *  This function adds the point (<B>x</B>,<B>y</B>) as a new point in
 *  the stroke.
 *
 * The footprint is updated and the new point is drawn on the drawing area.
 *
 *  \param [in] w_current The GschemToplevel object.
 *  \param [in] x        The X coord of the new point.
 *  \param [in] Y        The X coord of the new point.
 */
void
x_stroke_record (GschemToplevel *w_current, gint x, gint y)
{
  cairo_matrix_t user_to_device_matrix;
  double x0, y0;
  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);
  g_return_if_fail (geometry != NULL);

  g_assert (stroke_points != NULL);

  stroke_record (x, y);

  if (stroke_points->len < STROKE_MAX_POINTS) {
    StrokePoint point = { x, y };

    g_array_append_val (stroke_points, point);

    cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (GTK_WIDGET(view)));
    GedaColor *color = x_color_lookup (w_current, STROKE_COLOR);
    cairo_set_source_rgba (cr,
                           geda_color_get_red_double (color),
                           geda_color_get_green_double (color),
                           geda_color_get_blue_double (color),
                           geda_color_get_alpha_double (color));

    cairo_set_matrix (cr, gschem_page_geometry_get_world_to_screen_matrix (geometry));
    x0 = x;
    y0 = y;
    cairo_device_to_user (cr, &x0, &y0);
    cairo_get_matrix (cr, &user_to_device_matrix);
    cairo_save (cr);
    cairo_identity_matrix (cr);

    cairo_matrix_transform_point (&user_to_device_matrix, &x0, &y0);

    cairo_rectangle (cr, x0, y0, 1, 1);
    cairo_fill (cr);
    cairo_restore (cr);
    cairo_destroy (cr);
  }

}
Exemple #2
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
static void
a_zoom_box(GschemToplevel *w_current)
{
  double zx, zy, relativ_zoom_factor;
  double world_pan_center_x, world_pan_center_y;

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

  GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (page_view);
  g_return_if_fail (geometry != NULL);

  /*test if there is really a box*/
  if (w_current->first_wx == w_current->second_wx ||
      w_current->first_wy == w_current->second_wy) {
    s_log_message(_("Zoom too small!  Cannot zoom further.\n"));
    return;
  }

  /*calc new zoomfactors and choose the smaller one*/
  zx = (double) abs(geometry->viewport_left - geometry->viewport_right) / abs(w_current->first_wx - w_current->second_wx);
  zy = (double) abs(geometry->viewport_top - geometry->viewport_bottom) / abs(w_current->first_wy - w_current->second_wy);

  relativ_zoom_factor = (zx < zy ? zx : zy);

  /* calculate the center of the zoom box */
  world_pan_center_x = (w_current->first_wx + w_current->second_wx) / 2.0;
  world_pan_center_y = (w_current->first_wy + w_current->second_wy) / 2.0;

  /* and create the new window*/
  gschem_page_view_pan_general (page_view,
                                world_pan_center_x,
                                world_pan_center_y,
                                relativ_zoom_factor);
}
Exemple #3
0
/* dir is either ZOOM_IN, ZOOM_OUT or ZOOM_FULL which are defined in globals.h */
void
a_zoom(GschemToplevel *w_current, GschemPageView *page_view, int dir, int selected_from)
{
  g_return_if_fail (page_view != NULL);

  GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (page_view);
  g_return_if_fail (geometry != NULL);

  double world_pan_center_x,world_pan_center_y,relativ_zoom_factor = - 1;
  int start_x, start_y;
  double top, bottom, right, left;


  /* NB: w_current->zoom_gain is a percentage increase */
  switch(dir) {
  case(ZOOM_IN):
    relativ_zoom_factor = (100.0 + w_current->zoom_gain) / 100.0;
    break;

  case(ZOOM_OUT):
    relativ_zoom_factor = 100.0 / (100.0 + w_current->zoom_gain);
    break;

  case(ZOOM_FULL):
    /* indicate the zoom full with a negative zoomfactor */
    relativ_zoom_factor = -1;
    break;
  }

  /* calc center: either "mouse_to_world" or center=center or a
     virtual center if warp_cursor is disabled */
  if (w_current->zoom_with_pan == TRUE && selected_from == HOTKEY) {
    if (!x_event_get_pointer_position(w_current, FALSE,
				      &start_x, &start_y))
      return;
    if ( w_current->warp_cursor ) {
      world_pan_center_x = start_x;
      world_pan_center_y = start_y;
    } else {
      left = ((geometry->viewport_left - start_x) * (1/relativ_zoom_factor) + start_x);
      right = ((geometry->viewport_right - start_x) * (1/relativ_zoom_factor) + start_x);
      top = ((geometry->viewport_top - start_y) * (1/relativ_zoom_factor) + start_y);
      bottom = ((geometry->viewport_bottom - start_y) * (1/relativ_zoom_factor) + start_y);
      world_pan_center_x = (right + left) / 2;
      world_pan_center_y = (top + bottom) / 2;
    }
  } else {
    world_pan_center_x = (double) (geometry->viewport_left + geometry->viewport_right) / 2;
    world_pan_center_y = (double) (geometry->viewport_top + geometry->viewport_bottom) / 2;
  }

#if DEBUG
  printf("relative zoomfactor: %E\n", relativ_zoom_factor);
  printf("new center: x: %E, y: %E \n",
         world_pan_center_x, world_pan_center_y);
#endif


  /* calculate new window and draw it */
  gschem_page_view_pan_general (page_view,
                                world_pan_center_x,
                                world_pan_center_y,
                                relativ_zoom_factor);

  /* Before warping the cursor, filter out any consecutive scroll events
   * from the event queue.  If the program receives more than one scroll
   * event before it can process the first one, then the globals mouse_x
   * and mouse_y won't contain the proper mouse position,
   * because the handler for the mouse moved event needs to
   * run first to set these values.
   */
  GdkEvent *topEvent = gdk_event_get();
  while( topEvent != NULL ) {
    if( topEvent->type != GDK_SCROLL ) {
      gdk_event_put( topEvent );
      gdk_event_free( topEvent );
      break;
    }
    gdk_event_free( topEvent );
    topEvent = gdk_event_get();
  }

  /* warp the cursor to the right position */
  if (w_current->warp_cursor) {
     gschem_page_view_WORLDtoSCREEN (page_view,
                                     world_pan_center_x, world_pan_center_y,
                                     &start_x, &start_y);
     x_basic_warp_cursor (GTK_WIDGET (page_view), start_x, start_y);
  }
}
Exemple #4
0
/*! \brief Updates the preview widget.
 *  \par Function Description
 *  This function updates the preview: if the preview is active and a
 *  filename has been given, it opens the file and displays
 *  it. Otherwise it displays a blank page.
 *
 *  \param [in] preview The preview widget.
 */
static void
preview_update (Preview *preview)
{
  int left, top, right, bottom;
  int width, height;
  GError * err = NULL;

  GschemPageView *preview_view = GSCHEM_PAGE_VIEW (preview);

  g_return_if_fail (preview_view != NULL);
  PAGE *preview_page = gschem_page_view_get_page (preview_view);

  if (preview_page == NULL) {
    return;
  }

  TOPLEVEL *preview_toplevel = preview_page->toplevel;

  /* delete old preview */
  s_page_delete_objects (preview_toplevel, preview_page);

  if (preview->active) {
    g_assert ((preview->filename == NULL) || (preview->buffer == NULL));
    if (preview->filename != NULL) {
      /* open up file in current page */
      f_open_flags (preview_toplevel, preview_page,
                    preview->filename,
                    F_OPEN_RC | F_OPEN_RESTORE_CWD, NULL);
      /* test value returned by f_open... - Fix me */
      /* we should display something if there an error occured - Fix me */
    }
    if (preview->buffer != NULL) {
      /* Load the data buffer */
      GList * objects = o_read_buffer (preview_toplevel,
                                       NULL, preview->buffer, -1,
                                       _("Preview Buffer"), &err);

      if (err == NULL) {
        s_page_append_list (preview_toplevel, preview_page,
                            objects);
      }
      else {
        s_page_append (preview_toplevel, preview_page,
                       o_text_new(preview_toplevel, OBJ_TEXT, 2, 100, 100, LOWER_MIDDLE, 0,
                                  err->message, 10, VISIBLE, SHOW_NAME_VALUE));
        g_error_free(err);
      }
    }
  }

  if (world_get_object_glist_bounds (preview_toplevel,
                                     s_page_objects (preview_page),
                                     &left, &top,
                                     &right, &bottom)) {
    /* Clamp the canvas size to the extents of the page being previewed */
    width = right - left;
    height = bottom - top;

    GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (preview_view);
    geometry->world_left   = left   - ((double)width  * OVER_ZOOM_FACTOR);
    geometry->world_right  = right  + ((double)width  * OVER_ZOOM_FACTOR);
    geometry->world_top    = top    - ((double)height * OVER_ZOOM_FACTOR);
    geometry->world_bottom = bottom + ((double)height * OVER_ZOOM_FACTOR);
  }

  /* display current page (possibly empty) */
  gschem_page_view_zoom_extents (preview_view, NULL);
}
Exemple #5
0
/*! \brief Check if a bounding box is visible on the screen.
 *  \par Function Description
 *  This function checks if a given bounding box is visible on the screen.
 *
 *  WARNING: top and bottom are mis-named in world-coords,
 *  top is the smallest "y" value, and bottom is the largest.
 *  Be careful! This doesn't correspond to what you'd expect.
 *
 *  \param [in] w_current  The GschemToplevel object.
 *  \param [in] wleft      Left coordinate of the bounding box.
 *  \param [in] wtop       Top coordinate of the bounding box.
 *  \param [in] wright     Right coordinate of the bounding box.
 *  \param [in] wbottom    Bottom coordinate of the bounding box.
 *  \return TRUE if bounding box is visible, FALSE otherwise
 */
int visible (GschemToplevel *w_current,
             int wleft, int wtop, int wright, int wbottom)
{
  int visible=FALSE;
  GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (gschem_toplevel_get_current_page_view (w_current));

  visible = clip_nochange (geometry, wleft, wtop, wright, wtop);

#if DEBUG
  printf("vis1 %d\n", visible);
#endif

  if (!visible) {
    visible = clip_nochange (geometry, wleft, wbottom, wright, wbottom);
  } else {
    return(visible);
  }

#if DEBUG
  printf("vis2 %d\n", visible);
#endif

  if (!visible) {
    visible = clip_nochange (geometry, wleft, wtop, wleft, wbottom);
  } else {
    return(visible);
  }

#if DEBUG
  printf("vis3 %d\n", visible);
#endif

  if (!visible) {
    visible = clip_nochange (geometry, wright, wtop, wright, wbottom);
  } else {
    return(visible);
  }

#if DEBUG
  printf("vis4 %d\n", visible);
#endif

#if DEBUG
  printf("%d %d %d\n", wleft, geometry->viewport_top, wright);
  printf("%d %d %d\n", wtop, geometry->viewport_top, wbottom);
  printf("%d %d %d\n", wleft, geometry->viewport_right, wright);
  printf("%d %d %d\n", wtop, geometry->viewport_bottom, wbottom);
#endif

  /*
   * now check to see if bounding box encompasses the entire viewport.
   * We only need to test if one point on the screen clipping boundary
   * is indide the bounding box of the object.
   */
  if (geometry->viewport_left >= wleft  &&
      geometry->viewport_left <= wright &&
      geometry->viewport_top >= wtop    &&
      geometry->viewport_top <= wbottom ) {
    visible = 1;
  }

#if DEBUG
  printf("vis5 %d\n", visible);
#endif

  return(visible);
}
Exemple #6
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 *
 *  <B>flag</B> can be one of the following values:
 *  <DL>
 *    <DT>*</DT><DD>UNDO_ALL
 *    <DT>*</DT><DD>UNDO_VIEWPORT_ONLY
 *  </DL>
 */
void
o_undo_savestate (GschemToplevel *w_current, PAGE *page, int flag)
{
  TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
  char *filename = NULL;
  GList *object_list = NULL;
  int levels;
  UNDO *u_current;
  UNDO *u_current_next;

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

  g_return_if_fail (page != NULL);

  GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (view);

  /* save autosave backups if necessary */
  o_autosave_backups(w_current);

  if (w_current->undo_control == FALSE) {
    return;
  }

  if (flag == UNDO_ALL) {

    /* Increment the number of operations since last backup if
       auto-save is enabled */
    if (toplevel->auto_save_interval != 0) {
      page->ops_since_last_backup++;
    }

    /* HACK */
    /* Before we save the undo state, consolidate nets as necessary */

    /* This is where the net consolidation call would have been
     * triggered before it was removed from o_save_buffer().
     */
    if (toplevel->net_consolidate == TRUE)
      geda_net_object_consolidate (toplevel, page);
  }

  if (w_current->undo_type == UNDO_DISK && flag == UNDO_ALL) {

    filename = g_strdup_printf("%s%cgschem.save%d_%d.sch",
                               tmp_path, G_DIR_SEPARATOR,
                               prog_pid, undo_file_index++);

    /* Changed from f_save to o_save when adding backup copy creation. */
    /* f_save manages the creaton of backup copies.
       This way, f_save is called only when saving a file, and not when
       saving an undo backup copy */
    o_save (toplevel, s_page_objects (page), filename, NULL);

  } else if (w_current->undo_type == UNDO_MEMORY && flag == UNDO_ALL) {
    object_list = o_glist_copy_all (toplevel,
                                    s_page_objects (page),
                                    object_list);
  }

  /* Clear Anything above current */
  if (page->undo_current) {
    s_undo_remove_rest(toplevel, page->undo_current->next);
    page->undo_current->next = NULL;
  } else { /* undo current is NULL */
    s_undo_remove_rest(toplevel, page->undo_bottom);
    page->undo_bottom = NULL;
  }

  page->undo_tos = page->undo_current;

  if (geometry != NULL) {
    page->undo_tos = s_undo_add(page->undo_tos,
                                flag, filename, object_list,
                                (geometry->viewport_left + geometry->viewport_right) / 2,
                                (geometry->viewport_top + geometry->viewport_bottom) / 2,
                                /* scale */
                                max (((double) abs (geometry->viewport_right - geometry->viewport_left) / geometry->screen_width),
                                  ((double) abs (geometry->viewport_top - geometry->viewport_bottom) / geometry->screen_height)),
                                page->page_control,
                                page->up);
  } else {
    page->undo_tos = s_undo_add(page->undo_tos,
                                flag, filename, object_list,
                                0, /* center x */
                                0, /* center y */
                                0, /* scale */
                                page->page_control,
                                page->up);
  }

  page->undo_current =
      page->undo_tos;

  if (page->undo_bottom == NULL) {
    page->undo_bottom =
        page->undo_tos;
  }

#if DEBUG
  printf("\n\n---Undo----\n");
  s_undo_print_all(page->undo_bottom);
  printf("BOTTOM: %s\n", page->undo_bottom->filename);
  printf("TOS: %s\n", page->undo_tos->filename);
  printf("CURRENT: %s\n", page->undo_current->filename);
  printf("----\n");
#endif

  g_free(filename);

  /* Now go through and see if we need to free/remove some undo levels */
  /* so we stay within the limits */

  /* only check history every 10 undo savestates */
  if (undo_file_index % 10) {
    return;
  }

  levels = s_undo_levels(page->undo_bottom);

#if DEBUG
  printf("levels: %d\n", levels);
#endif

  if (levels >= w_current->undo_levels + UNDO_PADDING) {
    levels = levels - w_current->undo_levels;

#if DEBUG
    printf("Trimming: %d levels\n", levels);
#endif

    u_current = page->undo_bottom;

    while (levels > 0) {
      /* Because we use a pad you are always guaranteed to never */
      /* exhaust the list */
      g_assert (u_current != NULL);

      u_current_next = u_current->next;

      if (u_current->filename) {
#if DEBUG
        printf("Freeing: %s\n", u_current->filename);
#endif
        unlink(u_current->filename);
        g_free(u_current->filename);
      }

      if (u_current->object_list) {
        geda_object_list_delete (toplevel, u_current->object_list);
        u_current->object_list = NULL;
      }

      u_current->next = NULL;
      u_current->prev = NULL;
      g_free(u_current);

      u_current = u_current_next;
      levels--;
    }

    g_assert (u_current != NULL);
    u_current->prev = NULL;
    page->undo_bottom = u_current;

#if DEBUG
    printf("New current is: %s\n", u_current->filename);
#endif
  }

#if DEBUG
  printf("\n\n---Undo----\n");
  s_undo_print_all(page->undo_bottom);
  printf("BOTTOM: %s\n", page->undo_bottom->filename);
  printf("TOS: %s\n", page->undo_tos->filename);
  printf("CURRENT: %s\n", page->undo_current->filename);
  printf("----\n");
#endif

}
Exemple #7
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
}