Example #1
0
/*! \brief Translate a resource tree into a menu structure
 *
 *  \param [in] menu    The GHidMainMenu widget to be acted on
 *  \param [in] shall   The base menu shell (a menu bar or popup menu)
 *  \param [in] res     The base of the resource tree
 * */
void
ghid_main_menu_real_add_resource (GHidMainMenu *menu, GtkMenuShell *shell,
                                  const Resource *res)
{
    int i, j;
    const Resource *tmp_res;
    gchar mnemonic = 0;

    for (i = 0; i < res->c; ++i)
    {
        const gchar *accel = NULL;
        char *menu_label;
        const char *res_val;
        const Resource *sub_res = res->v[i].subres;
        GtkAction *action = NULL;

        switch (resource_type (res->v[i]))
        {
        case 101:   /* name, subres: passthrough */
            ghid_main_menu_real_add_resource (menu, shell, sub_res);
            break;
        case   1:   /* no name, subres */
            tmp_res = resource_subres (sub_res, "a");  /* accelerator */
            res_val = resource_value (sub_res, "m");   /* mnemonic */
            if (res_val)
                mnemonic = res_val[0];
            /* The accelerator resource will have two values, like
             *   a={"Ctrl-Q" "Ctrl<Key>q"}
             * The first Gtk ignores. The second needs to be translated. */
            if (tmp_res)
                accel = check_unique_accel
                        (translate_accelerator (tmp_res->v[1].value));

            /* Now look for the first unnamed value (not a subresource) to
             * figure out the name of the menu or the menuitem. */
            res_val = "button";
            for (j = 0; j < sub_res->c; ++j)
                if (resource_type (sub_res->v[j]) == 10)
                {
                    res_val = _(sub_res->v[j].value);
                    break;
                }
            /* Hack '_' in based on mnemonic value */
            if (!mnemonic)
                menu_label = g_strdup (res_val);
            else
            {
                char *post_ = strchr (res_val, mnemonic);
                if (post_ == NULL)
                    menu_label = g_strdup (res_val);
                else
                {
                    GString *tmp = g_string_new ("");
                    g_string_append_len (tmp, res_val, post_ - res_val);
                    g_string_append_c (tmp, '_');
                    g_string_append (tmp, post_);
                    menu_label = g_string_free (tmp, FALSE);
                }
            }
            /* If the subresource we're processing also has unnamed
             * subresources, it's a submenu, not a regular menuitem. */
            if (sub_res->flags & FLAG_S)
            {
                /* SUBMENU */
                GtkWidget *submenu = gtk_menu_new ();
                GtkWidget *item = gtk_menu_item_new_with_mnemonic (menu_label);
                GtkWidget *tearoff = gtk_tearoff_menu_item_new ();

                gtk_menu_shell_append (shell, item);
                gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);

                /* add tearoff to menu */
                gtk_menu_shell_append (GTK_MENU_SHELL (submenu), tearoff);
                /* recurse on the newly-added submenu */
                ghid_main_menu_real_add_resource (menu,
                                                  GTK_MENU_SHELL (submenu),
                                                  sub_res);
            }
            else
            {
                /* NON-SUBMENU: MENU ITEM */
                const char *checked = resource_value (sub_res, "checked");
                const char *label = resource_value (sub_res, "sensitive");
                const char *tip = resource_value (sub_res, "tip");
                if (checked)
                {
                    /* TOGGLE ITEM */
                    gchar *name = g_strdup_printf ("MainMenuAction%d",
                                                   action_counter++);

                    action = GTK_ACTION (gtk_toggle_action_new (name, menu_label,
                                         tip, NULL));
                    /* checked=foo       is a binary flag (checkbox)
                     * checked=foo,bar   is a flag compared to a value (radio) */
                    gtk_toggle_action_set_draw_as_radio
                    (GTK_TOGGLE_ACTION (action), !!strchr (checked, ','));
                }
                else if (label && strcmp (label, "false") == 0)
                {
                    /* INSENSITIVE ITEM */
                    GtkWidget *item = gtk_menu_item_new_with_label (menu_label);
                    gtk_widget_set_sensitive (item, FALSE);
                    gtk_menu_shell_append (shell, item);
                }
                else
                {
                    /* NORMAL ITEM */
                    gchar *name = g_strdup_printf ("MainMenuAction%d", action_counter++);
                    action = gtk_action_new (name, menu_label, tip, NULL);
                }
            }
            /* Connect accelerator, if there is one */
            if (action)
            {
                GtkWidget *item;
                gtk_action_set_accel_group (action, menu->accel_group);
                gtk_action_group_add_action_with_accel (menu->action_group,
                                                        action, accel);
                gtk_action_connect_accelerator (action);
                g_signal_connect (G_OBJECT (action), "activate", menu->action_cb,
                                  (gpointer) sub_res);
                g_object_set_data (G_OBJECT (action), "resource",
                                   (gpointer) sub_res);
                item = gtk_action_create_menu_item (action);
                gtk_menu_shell_append (shell, item);
                menu->actions = g_list_append (menu->actions, action);
                menu->special_key_cb (accel, action, sub_res);
            }
            /* Scan rest of resource in case there is more work */
            for (j = 0; j < sub_res->c; j++)
            {
                const char *res_name;
                /* named value = X resource */
                if (resource_type (sub_res->v[j]) == 110)
                {
                    res_name = sub_res->v[j].name;

                    /* translate bg, fg to background, foreground */
                    if (strcmp (res_name, "fg") == 0)   res_name = "foreground";
                    if (strcmp (res_name, "bg") == 0)   res_name = "background";

                    /* ignore special named values (m, a, sensitive) */
                    if (strcmp (res_name, "m") == 0
                            || strcmp (res_name, "a") == 0
                            || strcmp (res_name, "sensitive") == 0
                            || strcmp (res_name, "tip") == 0)
                        break;

                    /* log checked and active special values */
                    if (action && strcmp (res_name, "checked") == 0)
                        g_object_set_data (G_OBJECT (action), "checked-flag",
                                           sub_res->v[j].value);
                    else if (action && strcmp (res_name, "active") == 0)
                        g_object_set_data (G_OBJECT (action), "active-flag",
                                           sub_res->v[j].value);
                    else
                        /* if we got this far it is supposed to be an X
                         * resource.  For now ignore it and warn the user */
                        Message (_("The gtk gui currently ignores \"%s\""
                                   "as part of a menuitem resource.\n"
                                   "Feel free to provide patches\n"),
                                 sub_res->v[j].value);
                }
            }
            break;
        case  10:   /* no name, value */
            /* If we get here, the resource is "-" or "@foo" for some foo */
            if (res->v[i].value[0] == '@')
            {
                GList *children;
                int pos;

                children = gtk_container_get_children (GTK_CONTAINER (shell));
                pos = g_list_length (children);
                g_list_free (children);

                if (strcmp (res->v[i].value, "@layerview") == 0)
                {
                    menu->layer_view_shell = shell;
                    menu->layer_view_pos = pos;
                }
                else if (strcmp (res->v[i].value, "@layerpick") == 0)
                {
                    menu->layer_pick_shell = shell;
                    menu->layer_pick_pos = pos;
                }
                else if (strcmp (res->v[i].value, "@routestyles") == 0)
                {
                    menu->route_style_shell = shell;
                    menu->route_style_pos = pos;
                }
                else
                    Message (_("GTK GUI currently ignores \"%s\" in the menu\n"
                               "resource file.\n"), res->v[i].value);
            }
            else if (strcmp (res->v[i].value, "-") == 0)
            {
                GtkWidget *item = gtk_separator_menu_item_new ();
                gtk_menu_shell_append (shell, item);
            }
            else if (i > 0)
            {
                /* This is an action-less menuitem. It is really only useful
                 * when you're starting to build a new menu and you're looking
                 * to get the layout right. */
                GtkWidget *item
                    = gtk_menu_item_new_with_label (_(res->v[i].value));
                gtk_menu_shell_append (shell, item);
            }
            break;
        }
    }
}
Example #2
0
File: menu.c Project: thequux/pcb
static void
add_resource_to_menu (Widget menu, Resource * node, XtCallbackProc callback)
{
  int i, j;
  char *v;
  Widget sub, btn;
  Resource *r;

  for (i = 0; i < node->c; i++)
    switch (resource_type (node->v[i]))
      {
      case 101:		/* named subnode */
	n = 0;
	stdarg (XmNtearOffModel, XmTEAR_OFF_ENABLED);
	sub = XmCreatePulldownMenu (menu, node->v[i].name, args, n);
	XtSetValues (sub, args, n);
	n = 0;
	stdarg (XmNsubMenuId, sub);
	btn = XmCreateCascadeButton (menu, node->v[i].name, args, n);
	XtManageChild (btn);
	add_resource_to_menu (sub, node->v[i].subres, callback);
	break;

      case 1:			/* unnamed subres */
	n = 0;
#if 0
	if ((v = resource_value (node->v[i].subres, "fg")))
	  {
	    do_color (v, XmNforeground);
	  }
	if ((v = resource_value (node->v[i].subres, "bg")))
	  {
	    do_color (v, XmNbackground);
	  }
	if ((v = resource_value (node->v[i].subres, "font")))
	  {
	    XFontStruct *fs = XLoadQueryFont (display, v);
	    if (fs)
	      {
		XmFontList fl =
		  XmFontListCreate (fs, XmSTRING_DEFAULT_CHARSET);
		stdarg (XmNfontList, fl);
	      }
	  }
#endif
	if ((v = resource_value (node->v[i].subres, "m")))
	  {
	    stdarg (XmNmnemonic, v);
	  }
	if ((r = resource_subres (node->v[i].subres, "a")))
	  {
	    XmString as = XmStringCreateLocalized (r->v[0].value);
	    stdarg (XmNacceleratorText, as);
	    //stdarg(XmNaccelerator, r->v[1].value);
	    note_accelerator (r->v[1].value, node->v[i].subres);
	  }
	v = "button";
	for (j = 0; j < node->v[i].subres->c; j++)
	  if (resource_type (node->v[i].subres->v[j]) == 10)
	    {
	      v = node->v[i].subres->v[j].value;
	      break;
	    }
	stdarg (XmNlabelString, XmStringCreateLocalized (v));
	if (node->v[i].subres->flags & FLAG_S)
	  {
	    int nn = n;
	    stdarg (XmNtearOffModel, XmTEAR_OFF_ENABLED);
	    sub = XmCreatePulldownMenu (menu, v, args + nn, n - nn);
	    n = nn;
	    stdarg (XmNsubMenuId, sub);
	    btn = XmCreateCascadeButton (menu, "menubutton", args, n);
	    XtManageChild (btn);
	    add_resource_to_menu (sub, node->v[i].subres, callback);
	  }
	else
	  {
	    Resource *radio = resource_subres (node->v[i].subres, "radio");
	    char *checked = resource_value (node->v[i].subres, "checked");
	    char *label = resource_value (node->v[i].subres, "sensitive");
	    if (radio)
	      {
		ToggleItem *ti = (ToggleItem *) malloc (sizeof (ToggleItem));
		ti->next = toggle_items;
		ti->group = radio->v[0].value;
		ti->item = radio->v[1].value;
		ti->callback = callback;
		ti->node = node->v[i].subres;
		toggle_items = ti;

		if (resource_value (node->v[i].subres, "set"))
		  {
		    stdarg (XmNset, True);
		  }
		stdarg (XmNindicatorType, XmONE_OF_MANY);
		btn = XmCreateToggleButton (menu, "menubutton", args, n);
		ti->w = btn;
		XtAddCallback (btn, XmNvalueChangedCallback,
			       (XtCallbackProc) radio_callback,
			       (XtPointer) ti);
	      }
	    else if (checked)
	      {
		if (strchr (checked, ','))
		  stdarg (XmNindicatorType, XmONE_OF_MANY);
		else
		  stdarg (XmNindicatorType, XmN_OF_MANY);
		btn = XmCreateToggleButton (menu, "menubutton", args, n);
		XtAddCallback (btn, XmNvalueChangedCallback,
			       callback, (XtPointer) node->v[i].subres);
	      }
	    else if (label && strcmp (label, "false") == 0)
	      {
		stdarg (XmNalignment, XmALIGNMENT_BEGINNING);
		btn = XmCreateLabel (menu, "menulabel", args, n);
	      }
	    else
	      {
		btn = XmCreatePushButton (menu, "menubutton", args, n);
		XtAddCallback (btn, XmNactivateCallback,
			       callback, (XtPointer) node->v[i].subres);
	      }

	    for (j = 0; j < node->v[i].subres->c; j++)
	      switch (resource_type (node->v[i].subres->v[j]))
		{
		case 110:	/* named value = X resource */
		  {
		    char *n = node->v[i].subres->v[j].name;
		    if (strcmp (n, "fg") == 0)
		      n = "foreground";
		    if (strcmp (n, "bg") == 0)
		      n = "background";
		    if (strcmp (n, "m") == 0
			|| strcmp (n, "a") == 0
			|| strcmp (n, "sensitive") == 0)
		      break;
		    if (strcmp (n, "checked") == 0)
		      {
			note_widget_flag (btn, XmNset,
					  node->v[i].subres->v[j].value);
			break;
		      }
		    if (strcmp (n, "active") == 0)
		      {
			note_widget_flag (btn, XmNsensitive,
					  node->v[i].subres->v[j].value);
			break;
		      }
		    XtVaSetValues (btn, XtVaTypedArg,
				   n,
				   XtRString,
				   node->v[i].subres->v[j].value,
				   strlen (node->v[i].subres->v[j].value) + 1,
				   NULL);
		  }
		  break;
		}

	    XtManageChild (btn);
	  }
	break;

      case 10:			/* unnamed value */
	n = 0;
	if (node->v[i].value[0] == '@')
	  {
	    if (strcmp (node->v[i].value, "@layerview") == 0)
	      insert_layerview_buttons (menu);
	    if (strcmp (node->v[i].value, "@layerpick") == 0)
	      insert_layerpick_buttons (menu);
	    if (strcmp (node->v[i].value, "@routestyles") == 0)
	      lesstif_insert_style_buttons (menu);
	  }
	else if (strcmp (node->v[i].value, "-") == 0)
	  {
	    btn = XmCreateSeparator (menu, "sep", args, n);
	    XtManageChild (btn);
	  }
	else if (i > 0)
	  {
	    btn = XmCreatePushButton (menu, node->v[i].value, args, n);
	    XtManageChild (btn);
	  }
	break;
      }
}
Example #3
0
File: menu.c Project: thequux/pcb
Widget
lesstif_menu (Widget parent, char *name, Arg * margs, int mn)
{
  Widget mb = XmCreateMenuBar (parent, name, margs, mn);
  char *filename;
  Resource *r = 0, *bir;
  char *home_pcbmenu, *home;
  int screen;
  Resource *mr;

  display = XtDisplay (mb);
  screen = DefaultScreen (display);
  cmap = DefaultColormap (display, screen);

  /* homedir is set by the core */
  home = homedir;
  home_pcbmenu = NULL;
  if (home == NULL)
    {
      Message ("Warning:  could not determine home directory (from HOME)\n");
    }
  else 
    {
      home_pcbmenu = Concat (home, PCB_DIR_SEPARATOR_S, ".pcb", 
         PCB_DIR_SEPARATOR_S, "pcb-menu.res", NULL);
    }

  if (access ("pcb-menu.res", R_OK) == 0)
    filename = "pcb-menu.res";
  else if (home_pcbmenu != NULL && (access (home_pcbmenu, R_OK) == 0))
    filename = home_pcbmenu;
  else if (access (lesstif_pcbmenu_path, R_OK) == 0)
    filename = lesstif_pcbmenu_path;
  else
    filename = 0;

  bir = resource_parse (0, pcb_menu_default);
  if (!bir)
    {
      fprintf (stderr, "Error: internal menu resource didn't parse\n");
      exit(1);
    }

  if (filename)
    r = resource_parse (filename, 0);

  if (!r)
    r = bir;

  if (home_pcbmenu != NULL)
    {
      free (home_pcbmenu);
    }

  mr = resource_subres (r, "MainMenu");
  if (!mr)
    mr = resource_subres (bir, "MainMenu");
  if (mr)
    add_resource_to_menu (mb, mr, (XtCallbackProc) callback);

  mr = resource_subres (r, "Mouse");
  if (!mr)
    mr = resource_subres (bir, "Mouse");
  if (mr)
    load_mouse_resource (mr);


  if (do_dump_keys)
    DumpKeys2 ();

  return mb;
}
Example #4
0
int
ActionLoadVendorFrom (int argc, char **argv, Coord x, Coord y)
{
  int i;
  char *fname = NULL;
  static char *default_file = NULL;
  char *sval;
  Resource *res, *drcres, *drlres;
  int type;
  bool free_fname = false;

  cached_drill = -1;

  fname = argc ? argv[0] : 0;

  if (!fname || !*fname)
    {
      fname = gui->fileselect (_("Load Vendor Resource File..."),
			       _("Picks a vendor resource file to load.\n"
				 "This file can contain drc settings for a\n"
				 "particular vendor as well as a list of\n"
				 "predefined drills which are allowed."),
			       default_file, ".res", "vendor",
			       HID_FILESELECT_READ);
      if (fname == NULL)
	AFAIL (load_vendor);

      free_fname = true;

      free (default_file);
      default_file = NULL;

      if (fname && *fname)
	default_file = strdup (fname);
    }

  /* Unload any vendor table we may have had */
  n_vendor_drills = 0;
  n_refdes = 0;
  n_value = 0;
  n_descr = 0;
  FREE (vendor_drills);
  FREE (ignore_refdes);
  FREE (ignore_value);
  FREE (ignore_descr);


  /* load the resource file */
  res = resource_parse (fname, NULL);
  if (res == NULL)
    {
      Message (_("Could not load vendor resource file \"%s\"\n"), fname);
      return 1;
    }

  /* figure out the vendor name, if specified */
  vendor_name = (char *)UNKNOWN (resource_value (res, "vendor"));

  /* figure out the units, if specified */
  sval = resource_value (res, "units");
  if (sval == NULL)
    {
      sf = MIL_TO_COORD(1);
    }
  else if ((NSTRCMP (sval, "mil") == 0) || (NSTRCMP (sval, "mils") == 0))
    {
      sf = MIL_TO_COORD(1);
    }
  else if ((NSTRCMP (sval, "inch") == 0) || (NSTRCMP (sval, "inches") == 0))
    {
      sf = INCH_TO_COORD(1);
    }
  else if (NSTRCMP (sval, "mm") == 0)
    {
      sf = MM_TO_COORD(1);
    }
  else
    {
      Message ("\"%s\" is not a supported units.  Defaulting to inch\n",
	       sval);
      sf = INCH_TO_COORD(1);
    }


  /* default to ROUND_UP */
  rounding_method = ROUND_UP;

  /* extract the drillmap resource */
  drlres = resource_subres (res, "drillmap");
  if (drlres == NULL)
    {
      Message (_("No drillmap resource found\n"));
    }
  else
    {
      sval = resource_value (drlres, "round");
      if (sval != NULL)
	{
	  if (NSTRCMP (sval, "up") == 0)
	    {
	      rounding_method = ROUND_UP;
	    }
	  else if (NSTRCMP (sval, "nearest") == 0)
	    {
	      rounding_method = CLOSEST;
	    }
	  else
	    {
	      Message (_
		       ("\"%s\" is not a valid rounding type.  Defaulting to up\n"),
		       sval);
	      rounding_method = ROUND_UP;
	    }
	}

      process_skips (resource_subres (drlres, "skips"));

      for (i = 0; i < drlres->c; i++)
	{
	  type = resource_type (drlres->v[i]);
	  switch (type)
	    {
	    case 10:
	      /* just a number */
	      add_to_drills (drlres->v[i].value);
	      break;

	    default:
	      break;
	    }
	}
    }

  /* Extract the DRC resource */
  drcres = resource_subres (res, "drc");

  sval = resource_value (drcres, "copper_space");
  if (sval != NULL)
    {
      PCB->Bloat = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
	       0.01 * PCB->Bloat);
    }

  sval = resource_value (drcres, "copper_overlap");
  if (sval != NULL)
    {
      PCB->Shrink = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum copper overlap to %.2f mils\n"),
	       0.01 * PCB->Shrink);
    }

  sval = resource_value (drcres, "copper_width");
  if (sval != NULL)
    {
      PCB->minWid = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
	       0.01 * PCB->minWid);
    }

  sval = resource_value (drcres, "silk_width");
  if (sval != NULL)
    {
      PCB->minSlk = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum silk width to %.2f mils\n"),
	       0.01 * PCB->minSlk);
    }

  sval = resource_value (drcres, "min_drill");
  if (sval != NULL)
    {
      PCB->minDrill = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum drill diameter to %.2f mils\n"),
	       0.01 * PCB->minDrill);
    }

  sval = resource_value (drcres, "min_ring");
  if (sval != NULL)
    {
      PCB->minRing = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum annular ring to %.2f mils\n"),
	       0.01 * PCB->minRing);
    }

  Message (_("Loaded %d vendor drills from %s\n"), n_vendor_drills, fname);
  Message (_("Loaded %d RefDes skips, %d Value skips, %d Descr skips\n"),
	   n_refdes, n_value, n_descr);

  vendorMapEnable = true;
  apply_vendor_map ();
  if (free_fname)
    free (fname);
  return 0;
}