Exemple #1
0
static gboolean
textobj_transform(Textobj *textobj, const DiaMatrix *m)
{
  real a, sx, sy;

  g_return_val_if_fail(m != NULL, FALSE);

  if (!dia_matrix_get_angle_and_scales (m, &a, &sx, &sy)) {
    dia_log_message ("textobj_transform() can't convert given matrix");
    return FALSE;
  } else {
    /* XXX: what to do if width!=height */
    real height = text_get_height (textobj->text) * MIN(sx,sy);
    real angle = a*180/G_PI;
    Point p = textobj->object.position;

    /* rotation is invariant to the handle position */
    transform_point (&p, m);
    text_set_height (textobj->text, height);
    textobj->text_angle = angle;
    textobj->object.position = p;
 }

  textobj_update_data(textobj);
  return TRUE;
}
Exemple #2
0
static void
_action_done (GtkActionGroup *action_group,
	       GtkAction *action,
	       gpointer user_data)
{
  dia_log_message ("Done '%s'\n", gtk_action_get_name (action));
}
Exemple #3
0
/**
 * Basic (i.e. minimal) initialization of libdia. 
 *
 * It does not load any plug-ins but instead brings libdia to a state that plug-in loading can take place.
 * @param flags a set of DIA_INTERACTIVE, DIA_MESSAGE_STDERR
 */
void
libdia_init (guint flags)
{
  static gboolean initialized = FALSE;
  
  if (initialized)
    return;

  if (flags & DIA_MESSAGE_STDERR)
    set_message_func(stderr_message_internal);    
  LIBXML_TEST_VERSION;

#ifdef G_OS_WIN32
  xmlSetGenericErrorFunc(NULL, myXmlErrorReporting);
#endif

  if (flags & DIA_VERBOSE) {
    dia_log_message_enable (TRUE);
    dia_log_message ("initializing libdia");
  }
  stdprops_init();

  if (flags & DIA_INTERACTIVE) {
    char *diagtkrc;

    gtk_widget_set_default_colormap(gdk_rgb_get_cmap());

    diagtkrc = dia_config_filename("diagtkrc");
    dia_log_message ("Config from %s", diagtkrc);
    gtk_rc_parse(diagtkrc);
    g_free(diagtkrc);

    color_init();
  }
  initialized = TRUE;

  object_registry_init();

  /* The group_type is registered in app, but it needs to be exported anyway */
  object_register_type(&stdpath_type);
}
Exemple #4
0
/**
 * Basic (i.e. minimal) initialization of libdia. 
 *
 * It does not load any plug-ins but instead brings libdia to a state that plug-in loading can take place.
 * @param flags a set of DIA_INTERACTIVE, DIA_MESSAGE_STDERR
 */
void
libdia_init (guint flags)
{
  static gboolean initialized = FALSE;
  
  if (initialized)
    return;

  if (flags & DIA_MESSAGE_STDERR)
    set_message_func(stderr_message_internal);    
  LIBXML_TEST_VERSION;

#ifdef G_OS_WIN32
  xmlSetGenericErrorFunc(NULL, myXmlErrorReporting);
#endif

  if (flags & DIA_VERBOSE) {
    dia_log_message_enable (TRUE);
    dia_log_message ("initializing libdia");
  }
  stdprops_init();

  if (flags & DIA_INTERACTIVE) {
    char *diagtkrc;

    dia_image_init();

    diagtkrc = dia_config_filename("diagtkrc");
    dia_log_message ("Config from %s", diagtkrc);
    gtk_rc_parse(diagtkrc);
    g_free(diagtkrc);

    color_init();
  }
  initialized = TRUE;

  object_registry_init();
}
Exemple #5
0
/** Convert Base64 to pixbuf
 * @param b64 Base64 encoded data
 */
GdkPixbuf *
pixbuf_decode_base64 (const gchar *b64)
{
  /* see lib/prop_pixbuf.c(data_pixbuf) for a very similar implementation */
  GdkPixbuf *pixbuf = NULL;
  GdkPixbufLoader *loader;
  GError *error = NULL;

  loader = gdk_pixbuf_loader_new ();
  if (loader) {
    gint state = 0;
    guint save = 0;
#   define BUF_SIZE 4096
    guchar buf[BUF_SIZE];
    gchar *in = (gchar *)b64; /* direct access, not involving another xmlStrDup/xmlFree */
    gssize len = strlen (b64);
	
    do {
      gsize step = g_base64_decode_step (in,
					 len > BUF_SIZE ? BUF_SIZE : len,
					 buf, &state, &save);
      if (!gdk_pixbuf_loader_write (loader, buf, step, &error))
	break;

      in += BUF_SIZE;
      len -= BUF_SIZE;
    } while (len > 0);
    if (gdk_pixbuf_loader_close (loader, error ? NULL : &error)) {
      GdkPixbufFormat *format = gdk_pixbuf_loader_get_format (loader);
      gchar  *format_name = gdk_pixbuf_format_get_name (format);
      gchar **mime_types = gdk_pixbuf_format_get_mime_types (format);

      dia_log_message ("Loaded pixbuf from '%s' with '%s'\n", format_name, mime_types[0]);
      pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader));
      /* attach the mime-type to the pixbuf */
      g_object_set_data_full (G_OBJECT (pixbuf), "mime-type",
			      g_strdup (mime_types[0]),
			      (GDestroyNotify)g_free);
      g_strfreev (mime_types);
      g_free (format_name);
    } else {
      message_warning (_("Failed to load image form diagram:\n%s"), error->message);
      g_error_free (error);
    }

    g_object_unref (loader);
  }
  return pixbuf;
# undef BUF_SIZE
}
Exemple #6
0
void
ddisplay_flush(DDisplay *ddisp)
{
  /* if no update is queued, queue update
   *
   * GTK+ handles resize with higher priority than redraw
   * http://developer.gnome.org/gtk/2.24/gtk-General.html#GTK-PRIORITY-REDRAW:CAPS
   * GDK_PRIORITY_REDRAW = (G_PRIORITY_HIGH_IDLE + 20) with gtk-2-22
   * GTK_PRIORITY_RESIZE = (G_PRIORITY_HIGH_IDLE + 10)
   * Dia's canvas rendering is in between
   */
  if (!ddisp->update_id)
    ddisp->update_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE+15, (GSourceFunc)ddisplay_update_handler, ddisp, NULL);
  if (ddisp->display_areas) {
    IRectangle *r = (IRectangle *)ddisp->display_areas->data;
    dia_log_message ("DispUpdt: %4d,%3d - %4d,%3d\n", r->left, r->top, r->right, r->bottom);
  }
}
Exemple #7
0
/*!
 * Not sure why this service is not provided by GTK+.
 * We are passing tooltips into the actions (especially recent file menu).
 * But they were not shown without explicit setting on connect.
 */
static void
_ui_manager_connect_proxy (GtkUIManager *manager,
                           GtkAction    *action,
                           GtkWidget    *proxy)
{
  if (GTK_IS_MENU_ITEM (proxy))
    {
      gchar *tooltip;

      g_object_get (action, "tooltip", &tooltip, NULL);

      if (tooltip)
        {
	  gtk_widget_set_tooltip_text (proxy, tooltip);
	  g_free (tooltip);
	}
      else
	{
	  const gchar *name = gtk_action_get_name (action);

	  dia_log_message ("Action '%s' missing tooltip\n", name);
	}
    }
}
Exemple #8
0
void
app_init (int argc, char **argv)
{
  static gboolean nosplash = FALSE;
  static gboolean nonew = FALSE;
  static gboolean use_integrated_ui = TRUE;
  static gboolean credits = FALSE;
  static gboolean version = FALSE;
  static gboolean verbose = FALSE;
  static gboolean log_to_stderr = FALSE;
#ifdef HAVE_GNOME
  GnomeClient *client;
#endif
  static char *export_file_name = NULL;
  static char *export_file_format = NULL;
  static char *size = NULL;
  static char *show_layers = NULL;
  gboolean made_conversions = FALSE;
  GSList *files = NULL;
  static const gchar **filenames = NULL;
  int i = 0;

  gchar *export_format_string = 
     /* Translators:  The argument is a list of options, not to be translated */
    g_strdup_printf(_("Select the filter/format out of: %s"),
		    "cgm, dia, dxf, eps, eps-builtin, " EPS_PANGO
		    "fig, mp, plt, hpgl, png ("
#  if defined(HAVE_LIBPNG) && defined(HAVE_LIBART)
		    "png-libart, "
#  endif
#  ifdef HAVE_CAIRO
		    "cairo-png, cairo-alpha-png, "
#  endif
		    /* we always have pixbuf but don't know exactly all it's *few* save formats */
		    "pixbuf-png), jpg, "
		    "shape, svg, tex (pgf-tex, pstricks-tex), " WMF
		    "wpg");

  GOptionContext *context = NULL;
  static GOptionEntry options[] =
  {
    {"export", 'e', 0, G_OPTION_ARG_FILENAME, NULL /* &export_file_name */,
     N_("Export loaded file and exit"), N_("OUTPUT")},
    {"filter",'t', 0, G_OPTION_ARG_STRING, NULL /* &export_file_format */,
     NULL /* &export_format_string */, N_("TYPE") },
    {"size", 's', 0, G_OPTION_ARG_STRING, NULL,
     N_("Export graphics size"), N_("WxH")},
    {"show-layers", 'L', 0, G_OPTION_ARG_STRING, NULL,
     N_("Show only specified layers (e.g. when exporting). Can be either the layer name or a range of layer numbers (X-Y)"),
     N_("LAYER,LAYER,...")},
    {"nosplash", 'n', 0, G_OPTION_ARG_NONE, &nosplash,
     N_("Don't show the splash screen"), NULL },
    {"nonew", 'n', 0, G_OPTION_ARG_NONE, &nonew,
     N_("Don't create an empty diagram"), NULL },
    {"classic", '\0', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &use_integrated_ui,
     N_("Start classic user interface (no diagrams in tabs)"), NULL },
    {"log-to-stderr", 'l', 0, G_OPTION_ARG_NONE, &log_to_stderr,
     N_("Send error messages to stderr instead of showing dialogs."), NULL },
    {"input-directory", 'I', 0, G_OPTION_ARG_CALLBACK, _check_option_input_directory,
     N_("Directory containing input files"), N_("DIRECTORY")},
    {"output-directory", 'O', 0, G_OPTION_ARG_CALLBACK, _check_option_output_directory,
     N_("Directory containing output files"), N_("DIRECTORY")},
    {"credits", 'c', 0, G_OPTION_ARG_NONE, &credits,
     N_("Display credits list and exit"), NULL },
    {"verbose", 0, 0, G_OPTION_ARG_NONE, &verbose,
     N_("Generate verbose output"), NULL },
    {"version", 'v', 0, G_OPTION_ARG_NONE, &version,
     N_("Display version and exit"), NULL },
    { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, NULL /* &filenames */,
      NULL, NULL },
    { NULL }
  };
  
  /* for users of app_init() the default is interactive */
  dia_is_interactive = TRUE;

  options[0].arg_data = &export_file_name;
  options[1].arg_data = &export_file_format;
  options[1].description = export_format_string;
  options[2].arg_data = &size;
  options[3].arg_data = &show_layers;
  g_assert (strcmp (options[13].long_name, G_OPTION_REMAINING) == 0);
  options[13].arg_data = (void*)&filenames;

  argv0 = (argc > 0) ? argv[0] : "(none)";

#if GTK_CHECK_VERSION(2,24,0)
  /* ... use setlocale directly? */
#else
  gtk_set_locale();
#endif
  setlocale(LC_NUMERIC, "C");
  _setup_textdomains ();

  context = g_option_context_new(_("[FILE...]"));
  g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
#ifndef HAVE_GNOME
  /* avoid to add it a second time */
  g_option_context_add_group (context, gtk_get_option_group (FALSE));
#endif
  if (argv) {
    GError *error = NULL;

    if (!g_option_context_parse (context, &argc, &argv, &error)) {
      if (error) { /* IMO !error here is a bug upstream, triggered e.g. with --gdk-debug=updates */
	g_print ("%s", error->message);
	g_error_free (error);
      } else {
	g_print (_("Invalid option?"));
      }

      g_option_context_free(context);
      exit(1);
    }
    /* second level check of command line options, existance of input files etc. */
    if (filenames) {
      while (filenames[i] != NULL) {
	gchar *filename; 
	gchar *testpath;	  

	if (g_str_has_prefix (filenames[i], "file://")) {
	  filename = g_filename_from_uri (filenames[i], NULL, NULL);
	  if (!g_utf8_validate(filename, -1, NULL)) {
	    gchar *tfn = filename;
	    filename = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
	    g_free(tfn);
	  }
	} else
	  filename = g_filename_to_utf8 (filenames[i], -1, NULL, NULL, NULL);

	if (!filename) {
	  g_print (_("Filename conversion failed: %s\n"), filenames[i]);
	  continue;
	}

	if (g_path_is_absolute(filename))
	  testpath = filename;
	else
	  testpath = g_build_filename(input_directory ? input_directory : ".", filename, NULL);

	/* we still have a problem here, if GLib's file name encoding would not be utf-8 */
	if (g_file_test (testpath, G_FILE_TEST_IS_REGULAR))
	  files = g_slist_append(files, filename);
	else {
	  g_print (_("Missing input: %s\n"), filename);
	  g_free (filename);
	}
	if (filename != testpath)
	  g_free (testpath);
	++i;
      }
    }
    /* given some files to output, we are not starting up the UI */
    if (export_file_name || export_file_format || size)
      dia_is_interactive = FALSE;

  }

  if (argv && dia_is_interactive && !version) {
#ifdef HAVE_GNOME
    GnomeProgram *program =
      gnome_program_init (PACKAGE, VERSION, LIBGNOMEUI_MODULE,
			  argc, argv,
			  /* haven't found a quick way to pass GOption here */
			  GNOME_PARAM_GOPTION_CONTEXT, context,
			  GNOME_PROGRAM_STANDARD_PROPERTIES,
			  GNOME_PARAM_NONE);
    client = gnome_master_client();
    if(client == NULL) {
      g_warning(_("Can't connect to session manager!\n"));
    }
    else {
      g_signal_connect(G_OBJECT (client), "save_yourself",
		       G_CALLBACK (save_state), NULL);
      g_signal_connect(G_OBJECT (client), "die",
		       G_CALLBACK (session_die), NULL);
    }

    /* This smaller icon is 48x48, standard Gnome size */
    /* gnome_window_icon_set_default_from_file (GNOME_ICONDIR"/dia_gnome_icon.png");*/

#else
#  ifdef G_THREADS_ENABLED
    g_thread_init (NULL);
#  endif
    gtk_init(&argc, &argv);
#endif
  }
  else {
#ifdef G_THREADS_ENABLED
    g_thread_init (NULL);
#endif
    g_type_init();
    /*
     * On Windows there is no command line without display so that gtk_init is harmless. 
     * On X11 we need gtk_init_check() to avoid exit() just because there is no display 
     * running outside of X11.
     */
    if (!gtk_init_check(&argc, &argv))
      dia_log_message ("Running without display");
  }

  /* done with option parsing, don't leak */
  g_free(export_format_string);
  
  if (version) {
    gchar *ver_utf8;
    gchar *ver_locale;
#if (defined __TIME__) && (defined __DATE__)
    /* TRANSLATOR: 2nd and 3rd %s are time and date respectively. */
    ver_utf8 = g_strdup_printf(_("Dia version %s, compiled %s %s\n"), VERSION, __TIME__, __DATE__);
#else
    ver_utf8 = g_strdup_printf(_("Dia version %s\n"), VERSION);
#endif
    ver_locale = g_locale_from_utf8(ver_utf8, -1, NULL, NULL, NULL);
    printf("%s\n", ver_locale);
    g_free(ver_locale);
    g_free(ver_utf8);
    if (verbose)
      dump_dependencies();
    exit(0);
  }

  if (!dia_is_interactive)
    log_to_stderr = TRUE;

  libdia_init (   (dia_is_interactive ? DIA_INTERACTIVE : 0)
	       | (log_to_stderr ? DIA_MESSAGE_STDERR : 0)
	       | (verbose ? DIA_VERBOSE : 0) );

  print_credits(credits);

  if (dia_is_interactive) {
    create_user_dirs();

    if (!nosplash)
      app_splash_init("");

    /* Init cursors: */
    default_cursor = gdk_cursor_new(GDK_LEFT_PTR);
    ddisplay_set_all_cursor(default_cursor);
  }

  dia_register_plugins();
  dia_register_builtin_plugin(internal_plugin_init);

  load_all_sheets();     /* new mechanism */

  dia_log_message ("object defaults");
  {
    DiaContext *ctx = dia_context_new (_("Object Defaults"));
    dia_object_defaults_load (NULL, TRUE /* prefs.object_defaults_create_lazy */, ctx);
    dia_context_release (ctx);
  }
  debug_break();

  if (object_get_type("Standard - Box") == NULL) {
    message_error(_("Couldn't find standard objects when looking for "
		  "object-libs; exiting...\n"));
    g_critical( _("Couldn't find standard objects when looking for "
	    "object-libs in '%s'; exiting...\n"), dia_get_lib_directory("dia"));
    exit(1);
  }

  persistence_load();

  /** Must load prefs after persistence */
  prefs_init();

  if (dia_is_interactive) {

    /* further initialization *before* reading files */  
    active_tool = create_modify_tool();

    dia_log_message ("ui creation");
    if (use_integrated_ui) {
      create_integrated_ui();
    } else {
      create_toolbox();
      /* for the integrated ui case it is integrated */
      persistence_register_window_create("layer_window",
				         (NullaryFunc*)&layer_dialog_create);
    }
      
    /*fill recent file menu */
    recent_file_history_init();

    /* Set up autosave to check every 5 minutes */
    g_timeout_add_seconds(5*60, autosave_check_autosave, NULL);

#if 0 /* do we really open these automatically in the next session? */
    persistence_register_window_create("diagram_tree", 
                                       &diagram_tree_show);
#endif
    persistence_register_window_create("sheets_main_dialog",
				       (NullaryFunc*)&sheets_dialog_create);

    /* In current setup, we can't find the autosaved files. */
    /*autosave_restore_documents();*/

  }

  dia_log_message ("diagrams");
  made_conversions = handle_all_diagrams(files, export_file_name,
					 export_file_format, size, show_layers,
					 input_directory, output_directory);
					 
  if (dia_is_interactive && files == NULL && !nonew) {
    if (use_integrated_ui) {
      GList * list;
    
      file_new_callback(NULL);  
      list = dia_open_diagrams();
      if (list) {
        Diagram * diagram = list->data;
        diagram_update_extents(diagram);
        diagram->is_default = TRUE;
      }
    } else {
      gchar *filename = g_filename_from_utf8(_("Diagram1.dia"), -1, NULL, NULL, NULL);
      Diagram *diagram = new_diagram (filename);
      g_free(filename);
    
      if (diagram != NULL) {
        diagram_update_extents(diagram);
        diagram->is_default = TRUE;
        /* I think this is done in diagram_init() with a call to 
         * layer_dialog_update_diagram_list() */
        layer_dialog_set_diagram(diagram);
        new_display(diagram); 
      }
    }
  }
  g_slist_free(files);
  if (made_conversions) exit(0);

  dynobj_refresh_init();
  dia_log_message ("initialized");
}
Exemple #9
0
/** If all files produced by dia were good XML files, we wouldn't have to do
 *  this little gymnastic. Alas, during the libxml1 days, we were outputting
 *  files with no encoding specification (which means UTF-8 if we're in an
 *  asciish encoding) and strings encoded in local charset (so, we wrote
 *  broken files).
 *
 *  The following logic finds if we have a broken file, and attempts to fix
 *  it if it's possible. If the file is correct or is unrecognisable, we pass
 *  it untouched to libxml2.
 * @param filename The name of the file to check.
 * @param default_enc The default encoding to use if none is given.
 * @return The filename given if it seems ok, or the name of a new file
 *          with fixed contents, or NULL if we couldn't read the file.  The
 *          caller should free this string and unlink the file if it is not
 *          the same as `filename'.
 * @bug The many gzclose-g_free-return sequences should be refactored into
 *       an "exception handle" (goto+label). At least for people who think goto is
 *       better than this. I dont. --hb
 */
static const gchar *
xml_file_check_encoding(const gchar *filename, const gchar *default_enc)
{
  int fd = g_open (filename, O_RDONLY, 0);
  gzFile zf = gzdopen(fd,"rb");
  gchar *buf;
  gchar *p,*pmax;
  int len;
  gchar *tmp,*res;
  int uf;
  gboolean well_formed_utf8;

  static char magic_xml[] =
  {0x3c,0x3f,0x78,0x6d,0x6c,0x00}; /* "<?xml" in ASCII */

  if (!zf) {
    dia_log_message("%s can not be opened for encoding check (%s)", filename, fd > 0 ? "gzdopen" : "g_open");
    /* XXX perhaps we can just chicken out to libxml ? -- CC */
    return filename;
  }
  p = buf = g_malloc0(BUFLEN);
  len = gzread(zf,buf,BUFLEN);
  pmax = p + len;

  /* first, we expect the magic <?xml string */
  if ((0 != strncmp(p,magic_xml,5)) || (len < 5)) {
    gzclose(zf);
    g_free(buf);
    return filename; /* let libxml figure out what this is. */
  }
  /* now, we're sure we have some asciish XML file. */
  p += 5;
  while (((*p == 0x20)||(*p == 0x09)||(*p == 0x0d)||(*p == 0x0a))
         && (p<pmax)) p++;
  if (p>=pmax) { /* whoops ? */
    gzclose(zf);
    g_free(buf);
    return filename;
  }
  if (0 != strncmp(p,"version=\"",9)) {
    gzclose(zf); /* chicken out. */
    g_free(buf);
    return filename;
  }
  p += 9;
  /* The header is rather well formed. */
  if (p>=pmax) { /* whoops ? */
    gzclose(zf);
    g_free(buf);
    return filename;
  }
  while ((*p != '"') && (p < pmax)) p++;
  p++;
  while (((*p == 0x20)||(*p == 0x09)||(*p == 0x0d)||(*p == 0x0a))
         && (p<pmax)) p++;
  if (p>=pmax) { /* whoops ? */
    gzclose(zf);
    g_free(buf);
    return filename;
  }
  if (0 == strncmp(p,"encoding=\"",10)) {
    gzclose(zf); /* this file has an encoding string. Good. */
    g_free(buf);
    return filename;
  }
  /* now let's read the whole file, to see if there are offending bits.
   * We can call it well formed UTF-8 if the highest isn't used
   */
  well_formed_utf8 = TRUE;
  do {
    int i;
    for (i = 0; i < len; i++)
      if (buf[i] & 0x80 || buf[i] == '&')
        well_formed_utf8 = FALSE;
    len = gzread(zf,buf,BUFLEN);
  } while (len > 0 && well_formed_utf8);
  if (well_formed_utf8) {
    gzclose(zf); /* this file is utf-8 compatible  */
    g_free(buf);
    return filename;
  } else {
    gzclose(zf); /* poor man's fseek */
    fd = g_open (filename, O_RDONLY, 0);
    zf = gzdopen(fd,"rb");
    len = gzread(zf,buf,BUFLEN);
  }

  if (0 != strcmp(default_enc,"UTF-8")) {
    message_warning(_("The file %s has no encoding specification;\n"
                      "assuming it is encoded in %s"),
		    dia_message_filename(filename), default_enc);
  } else {
    gzclose(zf); /* we apply the standard here. */
    g_free(buf);
    return filename;
  }

  tmp = getenv("TMP");
  if (!tmp) tmp = getenv("TEMP");
  if (!tmp) tmp = "/tmp";

  res = g_strconcat(tmp,G_DIR_SEPARATOR_S,"dia-xml-fix-encodingXXXXXX",NULL);
  uf = g_mkstemp(res);
  write(uf,buf,p-buf);
  write(uf," encoding=\"",11);
  write(uf,default_enc,strlen(default_enc));
  write(uf,"\" ",2);
  write(uf,p,pmax - p);

  while (1) {
    len = gzread(zf,buf,BUFLEN);
    if (len <= 0) break;
    write(uf,buf,len);
  }
  gzclose(zf);
  close(uf);
  g_free(buf);
  return res; /* caller frees the name and unlinks the file. */
}
Exemple #10
0
/*!
 * \brief Align objects at their connected points
 *
 * The result of the algorithm depends on the order of objects
 * in the list. The list is typically coming from the selection.
 * That order depends on the kind of selection performed.
 *  - selection by rubberband gives objects in reverse order of
 *    the the original layer order as of this writing
 *  - Select/Transitive lets the order follow the connection order,
 *    but still reversed due data_select() prepending
 *  - Step-wise manual selection would also be in reverse order
 * So it appears to be a good idea to reverse the processing order
 * In this function to minimize surpise.
 *
 * The result also currently depends on the direction of the connections.
 * When aligning two objects the one connected with HANDLE_MOVE_ENDPOINT
 * will be moved. This might be contradictory to the selection order.
 *
 * @param objects  selection of objects to be considered
 * @param dia      the diagram owning the objects (and holding undo information)
 * @param align    unused
 */
void
object_list_align_connected (GList *objects, Diagram *dia, int align)
{
    GList *list;
    Point *orig_pos;
    Point *dest_pos;
    DiaObject *obj, *o2;
    int i, nobjs;
    GList *connected = NULL;
    GList *to_be_moved = NULL;
    GList *movelist = NULL;

    /* find all elements to be moved directly */
    filter_connected (objects, 2, &connected, &to_be_moved);
    dia_log_message ("Moves %d - Connections %d\n", g_list_length (to_be_moved), g_list_length (connected));
    /* for every connection check:
     * - "matching" directions of both object connection points (this also gives
     *    the direction of the move of the second object)
     * -
     * - move every object only once
     */
    nobjs = g_list_length (to_be_moved);
    orig_pos = g_new (Point, nobjs);
    dest_pos = g_new (Point, nobjs);

    list = g_list_reverse (connected);
    while (list != NULL) {
        DiaObject *con = list->data;
        Handle *h1 = NULL, *h2 = NULL;

        g_assert (con->num_handles >= 2);
        for (i = 0; i < con->num_handles; ++i) {
            if (con->handles[i]->id == HANDLE_MOVE_STARTPOINT)
                h1 = con->handles[i];
            else if (con->handles[i]->id == HANDLE_MOVE_ENDPOINT)
                h2 = con->handles[i];
        }
        /* should this be an assert? */
        if (h1 && h2 && h1->connected_to && h2->connected_to) {
            ConnectionPoint *cps = h1->connected_to;
            ConnectionPoint *cpe = h2->connected_to;

            obj = cps->object;
            o2 = cpe->object;
            /* swap alignment direction if we are working backwards by the selection order */
            if (g_list_index (to_be_moved, obj) < g_list_index (to_be_moved, o2)) {
                DiaObject *otmp = o2;
                ConnectionPoint *cptmp = cpe;
                o2 = obj;
                obj = otmp;
                cpe = cps;
                cps = cptmp;
            }
            if (   !g_list_find (movelist, o2)
                    && g_list_find(to_be_moved, o2) && g_list_find(to_be_moved, obj)) {
                Point delta = {0, 0};
                /* If we haven't moved it yet, check if we want to */
                int hweight = 0;
                int vweight = 0;
                if (cps->directions == DIR_NORTH || cps->directions == DIR_SOUTH)
                    ++vweight;
                else if (cps->directions == DIR_EAST || cps->directions == DIR_WEST)
                    ++hweight;
                if (cpe->directions == DIR_NORTH || cpe->directions == DIR_SOUTH)
                    ++vweight;
                else if (cpe->directions == DIR_EAST || cpe->directions == DIR_WEST)
                    ++hweight;

                /* One clear directions is required to move at all */
                if (vweight > hweight) {
                    /* horizontal move */
                    delta.x = cps->pos.x - cpe->pos.x;
                } else if (hweight > vweight) {
                    /* vertical move */
                    delta.y = cps->pos.y - cpe->pos.y;
                } else {
                    /* would need more context */
                    char dirs[] = "NESW";
                    int j;
                    for (j = 0; j < 4; ++j) if (cps->directions & (1<<j)) g_print ("%c", dirs[j]);
                    g_print ("(%s) -> ", obj->type->name);
                    for (j = 0; j < 4; ++j) if (cpe->directions & (1<<j)) g_print ("%c", dirs[j]);
                    g_print ("(%s)\n", o2->type->name);
                }
                if (delta.x != 0.0 || delta.y != 0) {
                    Point pos = o2->position;

                    point_add (&pos, &delta);

                    i = g_list_length (movelist);
                    orig_pos[i] = o2->position;
                    dest_pos[i] = pos;

                    dia_log_message ("Move '%s' by %g,%g\n", o2->type->name, delta.x, delta.y);
#if 0
                    o2->ops->move (o2, &pos);
#else
                    {
                        GList *move_list = g_list_append (NULL, o2);
                        object_list_move_delta (move_list, &delta);
                        g_list_free (move_list);
                    }
#endif
                    diagram_update_connections_object (dia, o2, TRUE);
                    movelist = g_list_append (movelist, o2);
                }
            }
        }

        list = g_list_next (list);
    }

    /* eating all the passed in parameters */
    undo_move_objects (dia, orig_pos, dest_pos, movelist);
    g_list_free (to_be_moved);
    g_list_free (connected);
}
Exemple #11
0
/*
 * Import (under construction)
 */
static void
import_object(DiaRenderer* self, DiagramData *dia,
              WPG_Type type, int iSize, guchar* pData)
{
  WpgImportRenderer *renderer = WPG_IMPORT_RENDERER(self);
  WPGPoint* pts = NULL;
  gint16* pInt16 = NULL;
  int    iNum = 0;
  gint32 iPre51 = 0;
  Point *points = NULL;

  switch (type) {
  case WPG_LINE:
    iNum = 2;
    pts = (WPGPoint*)pData;
    points = _make_points (renderer, pts, iNum);
    DIA_RENDERER_GET_CLASS(renderer)->draw_line (self, &points[0], &points[1], &renderer->stroke);
    break;
  case WPG_POLYLINE:
    pInt16 = (gint16*)pData;
    iNum = pInt16[0];
    pts = (WPGPoint*)(pData + sizeof(gint16));
    points = _make_points (renderer, pts, iNum);
    DIA_RENDERER_GET_CLASS(renderer)->draw_polyline (self, points, iNum, &renderer->stroke);
    break;
  case WPG_RECTANGLE:
    points = _make_rect (renderer, (WPGPoint*)pData);
    _do_rect (renderer, points);
    break;
  case WPG_POLYGON:
    pInt16 = (gint16*)pData;
    iNum = pInt16[0];
    pts = (WPGPoint*)(pData + sizeof(gint16));
    points = _make_points (renderer, pts, iNum);
    _do_polygon (renderer, points, iNum);
    break;
  case WPG_ELLIPSE:
    {
      WPGEllipse* pEll = (WPGEllipse*)pData;
      _do_ellipse (renderer, pEll);
    }
    break;
  case WPG_POLYCURVE:
    iPre51 = *((gint32*)pData);
    pInt16 = (gint16*)pData;
    iNum = pInt16[2];
    pts = (WPGPoint*)(pData + 3*sizeof(gint16));
    dia_log_message ("WPG POLYCURVE Num pts %d Pre51 %d", iNum, iPre51);
    _do_bezier (renderer, pts, iNum);
    break;
  case WPG_FILLATTR:
  case WPG_LINEATTR:
  case WPG_COLORMAP:
  case WPG_MARKERATTR:
  case WPG_POLYMARKER:
  case WPG_TEXTSTYLE:
  case WPG_START:
  case WPG_END:
  case WPG_OUTPUTATTR:
  case WPG_STARTFIGURE:
  case WPG_STARTCHART:
  case WPG_PLANPERFECT:
  case WPG_STARTWPG2:
  case WPG_POSTSCRIPT1:
  case WPG_POSTSCRIPT2:
    /* these are no objects, silence GCC */
    break;
  case WPG_BITMAP1:
  case WPG_TEXT:
  case WPG_BITMAP2:
    /* these objects are handled directly below, silence GCC */
    break;
  case WPG_GRAPHICSTEXT2:
  case WPG_GRAPHICSTEXT3:
    /* these objects actually might get implemented some day, silence GCC */
    break;
  } /* switch */
  g_free (points);
  DIAG_NOTE(g_message("Type %d Num pts %d Size %d", type, iNum, iSize));
}