Пример #1
0
/*! \brief Find the closest grid coordinate.
 *  \par Function Description
 *  This function snaps the current input coordinate to the
 *  closest grid coordinate.
 *
 *  \param [in] w_current  The GschemToplevel object.
 *  \param [in] input      The coordinate to snap.
 *  \return The closest grid coordinate to the input.
 */
int snap_grid(GschemToplevel *w_current, int input)
{
  int p, m, n;
  int sign, value, snap_size;
  SNAP_STATE snap_mode;

  snap_mode = gschem_options_get_snap_mode (w_current->options);
  snap_size = gschem_options_get_snap_size (w_current->options);

  if (snap_mode == SNAP_OFF) {
    return(input);
  }

  /* this code was inspired from killustrator, it's much simpler than mine */
  sign = ( input < 0 ? -1 : 1 );
  value = abs(input);

  p = value / snap_size;
  m = value % snap_size;
  n = p * snap_size;
  if (m > snap_size / 2)
  n += snap_size;

#if DEBUG
  printf("p: %d\n", p);
  printf("m: %d\n", m);
  printf("m > snap_size / 2: %d\n", (m > snap_size / 2));
  printf("n: %d\n", n);
  printf("n*s: %d\n", n*sign);
#endif

  return(sign*n);
}
Пример #2
0
/*! \private
 *  \brief Get a property
 *
 *  \param [in]     object
 *  \param [in]     param_id
 *  \param [in,out] value
 *  \param [in]     pspec
 */
static void
get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec)
{
  GschemOptions *options = GSCHEM_OPTIONS (object);

  switch (param_id) {
    case PROP_GRID_MODE:
      g_value_set_int (value, gschem_options_get_grid_mode (options));
      break;

    case PROP_MAGNETIC_NET_MODE:
      g_value_set_boolean (value, gschem_options_get_magnetic_net_mode (options));
      break;

    case PROP_NET_RUBBER_BAND_MODE:
      g_value_set_boolean (value, gschem_options_get_net_rubber_band_mode (options));
      break;

    case PROP_SNAP_MODE:
      g_value_set_int (value, gschem_options_get_snap_mode (options));
      break;

    case PROP_SNAP_SIZE:
      g_value_set_int (value, gschem_options_get_snap_size (options));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
  }
}
Пример #3
0
/*! \private
 *  \brief Update the snap mode widget with the current value
 *
 *  \param [in,out] widget This widget
 */
static void
update_snap_mode_widget (GschemOptionsWidget *widget)
{
  g_return_if_fail (widget != NULL);

  if (widget->options != NULL) {
    int index;
    SNAP_STATE snap_mode;

    snap_mode = gschem_options_get_snap_mode (widget->options);

    for (index=0; index<SNAP_STATE_COUNT; index++) {
      g_signal_handlers_block_by_func (G_OBJECT (widget->snap_radio[index]),
                                       G_CALLBACK (update_snap_mode_model),
                                       widget);
    }

    for (index=0; index<SNAP_STATE_COUNT; index++) {
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget->snap_radio[index]),
                                    (snap_mode == index));
  }

    for (index=0; index<SNAP_STATE_COUNT; index++) {
      g_signal_handlers_unblock_by_func (G_OBJECT (widget->snap_radio[index]),
                                         G_CALLBACK (update_snap_mode_model),
                                         widget);
    }
  }
}
Пример #4
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void x_window_create_main(GschemToplevel *w_current)
{
  TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);

  GtkPolicyType policy;
  GtkWidget *main_box=NULL;
  GtkWidget *menubar=NULL;
  GtkWidget *toolbar=NULL;
  GtkWidget *handlebox=NULL;
  GtkWidget *hscrollbar;
  GtkWidget *vscrollbar;
  GtkAdjustment *hadjustment;
  GtkAdjustment *vadjustment;
  char *right_button_text;

  /* used to signify that the window isn't mapped yet */
  w_current->window = NULL;

  w_current->main_window = GTK_WIDGET (gschem_main_window_new ());

  gtk_widget_set_name (w_current->main_window, "gschem");
  gtk_window_set_policy (GTK_WINDOW (w_current->main_window), TRUE, TRUE, TRUE);

  /* We want the widgets to flow around the drawing area, so we don't
   * set a size of the main window.  The drawing area's size is fixed,
   * see below
   */

   /*
    * normally we let the window manager handle locating and sizing
    * the window.  However, for some batch processing of schematics
    * (generating a pdf of all schematics for example) we want to
    * override this.  Hence "auto_place_mode".
    */
   if( auto_place_mode )
   	gtk_widget_set_uposition (w_current->main_window, 10, 10);

  /* this should work fine */
  g_signal_connect (G_OBJECT (w_current->main_window), "delete_event",
                    G_CALLBACK (i_callback_close_wm),
                    w_current);

  /* Containers first */
  main_box = gtk_vbox_new(FALSE, 1);
  gtk_container_border_width(GTK_CONTAINER(main_box), 0);
  gtk_container_add(GTK_CONTAINER(w_current->main_window), main_box);

  menubar = get_main_menu (w_current);
  if (w_current->handleboxes) {
  	handlebox = gtk_handle_box_new ();
  	gtk_box_pack_start(GTK_BOX(main_box), handlebox, FALSE, FALSE, 0);
  	gtk_container_add (GTK_CONTAINER (handlebox), menubar);
  } else {
  	gtk_box_pack_start(GTK_BOX(main_box), menubar, FALSE, FALSE, 0);
  }

  w_current->menubar = menubar;
  gtk_widget_realize (w_current->main_window);

  if (w_current->handleboxes && w_current->toolbars) {
  	handlebox = gtk_handle_box_new ();
  	gtk_box_pack_start (GTK_BOX (main_box), handlebox, FALSE, FALSE, 0);
  }

  if (w_current->toolbars) {
    toolbar = gtk_toolbar_new();
    gtk_toolbar_set_orientation (GTK_TOOLBAR(toolbar),
                                 GTK_ORIENTATION_HORIZONTAL);
    gtk_toolbar_set_style (GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);

    if (w_current->handleboxes) {
      gtk_container_add (GTK_CONTAINER (handlebox), toolbar);
    } else {
      gtk_box_pack_start(GTK_BOX(main_box), toolbar, FALSE, FALSE, 0);
    }

    gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                             _("New"),
                             _("New file"),
                             "toolbar/new",
                             x_window_stock_pixmap("new", w_current),
                             (GtkSignalFunc) i_callback_toolbar_file_new,
                             w_current);
    gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                             _("Open"),
                             _("Open file..."),
                             "toolbar/open",
                             x_window_stock_pixmap("open", w_current),
                             (GtkSignalFunc) i_callback_toolbar_file_open,
                             w_current);
    gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                             _("Save"),
                             _("Save file"),
                             "toolbar/save",
                             x_window_stock_pixmap("save", w_current),
                             (GtkSignalFunc) i_callback_toolbar_file_save,
                             w_current);
    gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
    gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                             _("Undo"),
                             _("Undo last operation"),
                             "toolbar/undo",
                             x_window_stock_pixmap("undo", w_current),
                             (GtkSignalFunc) i_callback_toolbar_edit_undo,
                             w_current);
    gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                             _("Redo"),
                             _("Redo last undo"),
                             "toolbar/redo",
                             x_window_stock_pixmap("redo", w_current),
                             (GtkSignalFunc) i_callback_toolbar_edit_redo,
                             w_current);
    gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
    /* not part of any radio button group */
    gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                             _("Component"),
                             _("Add component...\nSelect library and component from list, move the mouse into main window, click to place\nRight mouse button to cancel"),
                             "toolbar/component",
                             x_window_stock_pixmap("insert-symbol", w_current),
                             (GtkSignalFunc) i_callback_toolbar_add_component,
                             w_current);
    w_current->toolbar_net =
      gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
                                 GTK_TOOLBAR_CHILD_RADIOBUTTON,
                                 NULL,
                                 _("Nets"),
                                 _("Add nets mode\nRight mouse button to cancel"),
                                 "toolbar/nets",
                                 x_window_stock_pixmap("insert-net", w_current),
                                 (GtkSignalFunc) i_callback_toolbar_add_net,
                                 w_current);
    w_current->toolbar_bus =
      gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
                                 GTK_TOOLBAR_CHILD_RADIOBUTTON,
                                 w_current->toolbar_net,
                                 _("Bus"),
                                 _("Add buses mode\nRight mouse button to cancel"),
                                 "toolbar/bus",
                                 x_window_stock_pixmap("insert-bus", w_current),
                                 (GtkSignalFunc) i_callback_toolbar_add_bus,
                                 w_current);
    /* not part of any radio button group */
    gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
                             _("Text"),
                             _("Add Text..."),
                             "toolbar/text",
                             x_window_stock_pixmap("insert-text", w_current),
                             (GtkSignalFunc) i_callback_toolbar_add_text,
                             w_current);
    gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
    w_current->toolbar_select =
      gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
                                 GTK_TOOLBAR_CHILD_RADIOBUTTON,
                                 w_current->toolbar_bus,
                                 _("Select"),
                                 _("Select mode"),
                                 "toolbar/select",
                                 x_window_stock_pixmap("select", w_current),
                                 (GtkSignalFunc) i_callback_toolbar_edit_select,
                                 w_current);


    gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_current->toolbar_select),
                                 TRUE);
  }


  /*  Try to create popup menu (appears in right mouse button  */
  w_current->popup_menu = (GtkWidget *) get_main_popup(w_current);


  /* Setup a GtkScrolledWindow for the drawing area */
  hadjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0,
                                                    0.0,
                                                    toplevel->init_right,
                                                    100.0,
                                                    100.0,
                                                    10.0));

  vadjustment = GTK_ADJUSTMENT (gtk_adjustment_new (toplevel->init_bottom,
                                                    0.0,
                                                    toplevel->init_bottom,
                                                    100.0,
                                                    100.0,
                                                    10.0));

  w_current->scrolled = gtk_scrolled_window_new (hadjustment, vadjustment);
  gtk_container_add(GTK_CONTAINER(main_box), w_current->scrolled);
  x_window_create_drawing(w_current->scrolled, w_current);
  x_window_setup_draw_events(w_current);

  policy = (w_current->scrollbars_flag) ? GTK_POLICY_ALWAYS : GTK_POLICY_NEVER;
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (w_current->scrolled), policy, policy);

  hscrollbar = gtk_scrolled_window_get_hscrollbar (GTK_SCROLLED_WINDOW (w_current->scrolled));
  gtk_range_set_update_policy (GTK_RANGE (hscrollbar), GTK_UPDATE_CONTINUOUS);

  vscrollbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (w_current->scrolled));
  gtk_range_set_update_policy (GTK_RANGE (vscrollbar), GTK_UPDATE_CONTINUOUS);

  /* macro box */
  w_current->macro_widget = GTK_WIDGET (g_object_new (GSCHEM_TYPE_MACRO_WIDGET, NULL));

  gtk_box_pack_start (GTK_BOX (main_box),
                      w_current->macro_widget,
                      FALSE,
                      FALSE,
                      0);

  g_signal_connect (w_current->macro_widget,
                    "response",
                    G_CALLBACK (&x_window_invoke_macro),
                    w_current);

  /* bottom box */
  if (default_third_button == POPUP_ENABLED) {
    right_button_text = _("Menu/Cancel");
  } else {
    right_button_text = _("Pan/Cancel");
  }

  w_current->bottom_widget = GTK_WIDGET (g_object_new (GSCHEM_TYPE_BOTTOM_WIDGET,
      "grid-mode",          gschem_options_get_grid_mode (w_current->options),
      "grid-size",          gschem_options_get_snap_size (w_current->options), /* x_grid_query_drawn_spacing (w_current), -- occurs before the page is set */
      "left-button-text",   _("Pick"),
      "middle-button-text", _("none"),
      "right-button-text",  right_button_text,
      "snap-mode",          gschem_options_get_snap_mode (w_current->options),
      "snap-size",          gschem_options_get_snap_size (w_current->options),
      "status-text",        _("Select Mode"),
      NULL));

  i_update_middle_button (w_current, NULL, NULL);

  gtk_box_pack_start (GTK_BOX (main_box), w_current->bottom_widget, FALSE, FALSE, 0);

  gtk_widget_show_all (w_current->main_window);

  w_current->window = w_current->drawing_area->window;

  w_current->drawable = w_current->window;

  x_window_setup_gc(w_current);
}
Пример #5
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void o_move_motion (GschemToplevel *w_current, int w_x, int w_y)
{
  GList *selection, *s_current;
  OBJECT *object;
  gint object_x, object_y;
  gboolean resnap = FALSE;
  SNAP_STATE snap_mode;

  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);
  g_return_if_fail (page->place_list != NULL);

  snap_mode = gschem_options_get_snap_mode (w_current->options);

  selection = geda_list_get_glist (page->selection_list);

  /* realign the object if we are in resnap mode */
  if ((selection != NULL) && (snap_mode == SNAP_RESNAP)) {
    if (g_list_length(selection) > 1) {
      /* find an object that is not attached to any other object */
      for (s_current = selection;
           s_current != NULL;
           s_current = g_list_next(s_current)) {
        if (((OBJECT *) s_current->data)->attached_to == NULL) {
          object = (OBJECT *) s_current->data;
          resnap = TRUE;
          break;
        }
      }

      /* Only resnap single elements. This is also the case if
         the selection contains one object and all other object
         elements are attributes of the object element.*/
      for (s_current = selection;
           s_current != NULL && resnap == TRUE;
           s_current = g_list_next(s_current)) {
        if (!(object == (OBJECT *) s_current->data)
            && !o_attrib_is_attached(page->toplevel,
                                     (OBJECT *) s_current->data, object)) {
          resnap = FALSE;
        }
      }
    } else { /* single object */
      resnap = TRUE;
      object = (OBJECT *) selection->data;
    }

    /* manipulate w_x and w_y in a way that will lead to a position
       of the object that is aligned with the grid */
    if (resnap) {
      if (o_get_position(page->toplevel, &object_x, &object_y, object)) {
        w_x += snap_grid (w_current, object_x) - object_x;
        w_y += snap_grid (w_current, object_y) - object_y;
      }
    }
  }

  o_move_invalidate_rubber (w_current, FALSE);
  w_current->second_wx = w_x;
  w_current->second_wy = w_y;
  o_move_invalidate_rubber (w_current, TRUE);
}
Пример #6
0
/*! \brief Handle motion during a move operation, resnapping if necessary
 * \par Function Description
 * Handle movement during a move operation, by updating the global
 * candidate transformation parameters.  The \a w_x and \b w_y
 * parameters are the incremental translation to be handled.
 *
 * This function mostly exists to implement the "resnapping" logic,
 * which destructively puts objects back onto the grid during a move
 * operation, as long as specific criteria are met.
 *
 * \param w_current  Global gschem state structure.
 * \param w_x        X-axis translation
 * \param w_y        Y-axis translation
 */
void o_move_motion (GschemToplevel *w_current, int w_x, int w_y)
{
  GList *selection, *s_current;
  OBJECT *object = NULL;
  gint object_x, object_y;
  SNAP_STATE snap_mode;

  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);
  g_return_if_fail (page->place_list != NULL);

  snap_mode = gschem_options_get_snap_mode (w_current->options);

  selection = geda_list_get_glist (page->selection_list);

  /* There are three posssibilities:
   *
   * 1. There is exactly one object selected, in which case it is
   *    snapped.
   *
   * 2. There are multiple objects selected, but there is some object
   *    O[i] such that all other selected objects O[j!=i] are attached
   *    as attributes of O[i].  In that case, the O[i] is snapped.
   *
   * 3. Other cases, in which case no snapping occurs.
   */

  if (NULL == selection || SNAP_RESNAP != snap_mode) {
    object = NULL;

  } else if (1 == g_list_length (selection)) {
    object = (OBJECT *) selection->data;

  } else {

    /* The object that things are supposed to be attached to */
    OBJECT *attached = NULL;

    /* Scan the selection, searching for an object that's not attached
     * to any other object.  As we go, also check whether everything
     * in the list that *is* attached as an attribute is attached to
     * the same object. */
    for (s_current = selection;
         NULL != s_current;
         s_current = g_list_next (s_current)) {

      OBJECT *candidate = (OBJECT *) s_current->data;

      if (NULL == candidate->attached_to) {

        /* If the object is *not* attached as an attribute, then check
         * whether we previously found an independent object.  If we
         * did, we can't do snapping, so give up. */
        if (NULL == object) {
          object = candidate;
        } else if (candidate != object) {
          break; /* Give up */
        }

      } else {

        /* If the object is attached as an attribute, then check if
         * it's attached as an attribute of the same object as
         * everything else is.  If not, we can't do snapping, so give
         * up. */
        if (NULL == attached) {
          attached = candidate->attached_to;
        } else if (attached != candidate->attached_to) {
          break; /* Give up */
        }
      }
    }

    if (NULL == object ||
        (NULL != attached && object != attached)) {
      object = NULL;
    } else {
      g_assert (NULL != object);
    }
  }

  /* manipulate w_x and w_y in a way that will lead to a position
     of the object that is aligned with the grid */
  if (NULL != object) {
    if (geda_object_get_position (object, &object_x, &object_y)) {
      w_x += snap_grid (w_current, object_x) - object_x;
      w_y += snap_grid (w_current, object_y) - object_y;
    }
  }

  o_move_invalidate_rubber (w_current, FALSE);
  w_current->second_wx = w_x;
  w_current->second_wy = w_y;
  o_move_invalidate_rubber (w_current, TRUE);
}