示例#1
0
static gboolean
run_color_chooser_dialog (gpointer user_data)
{
	EColorChooserWidgetPrivate *priv;
	GtkWidget *parent_window;
	GtkWidget *parent_chooser;
	GtkWidget *dialog;
	GtkWidget *chooser;

	parent_chooser = user_data;

	g_object_set (
		G_OBJECT (parent_chooser), "show-editor", FALSE, NULL);

	parent_window = g_object_get_data (G_OBJECT (parent_chooser), "window");
	if (!parent_window)
		parent_window = gtk_widget_get_toplevel (parent_chooser);
	dialog = gtk_dialog_new_with_buttons (
		N_("Choose custom color"),
		GTK_WINDOW (parent_window),
		GTK_DIALOG_MODAL,
		_("_Cancel"), GTK_RESPONSE_REJECT,
		_("_OK"), GTK_RESPONSE_ACCEPT, NULL);

	chooser = gtk_color_chooser_widget_new ();
	g_object_set (G_OBJECT (chooser), "show-editor", TRUE, NULL);
	gtk_box_pack_start (
		GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
		chooser, TRUE, TRUE, 5);

	gtk_widget_show_all (chooser);

	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
		GdkRGBA color;

		gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (chooser), &color);
		gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (parent_chooser), &color);

		g_signal_emit_by_name (parent_chooser, "color-activated", &color);
	}

	gtk_widget_destroy (dialog);

	priv = E_COLOR_CHOOSER_WIDGET_GET_PRIVATE (parent_chooser);
	priv->showing_editor = FALSE;

	return FALSE;
}
示例#2
0
static GtkWidget *
create_color_sel (GtkWidget *parent_widget, GObject *action_proxy,
		  GOColor c, GCallback handler, gboolean allow_alpha)
{
	const char *title =
		g_object_get_data (G_OBJECT (action_proxy), "title");
	GtkWidget *toplevel = gtk_widget_get_toplevel (parent_widget);
	GtkWidget *dialog = gtk_dialog_new_with_buttons
		(title,
		 (gtk_widget_is_toplevel (toplevel)
		  ? GTK_WINDOW (toplevel)
		  : NULL),
		 GTK_DIALOG_DESTROY_WITH_PARENT,
		 GTK_STOCK_OK, GTK_RESPONSE_OK,
		 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
		 NULL);
	GtkWidget *ccw = gtk_color_chooser_widget_new ();
	GtkWidget *dca = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
	GdkRGBA gdk;

	g_object_set_data (G_OBJECT (dialog), CCW_KEY, ccw);

	gtk_container_add (GTK_CONTAINER (dca), ccw);

	go_color_to_gdk_rgba (c, &gdk);

	g_object_set (G_OBJECT (ccw),
		      "use-alpha", allow_alpha,
		      "rgba", &gdk,
		      "show-editor", TRUE,
		      NULL);

	g_signal_connect_object (dialog,
		"response", handler, action_proxy, 0);

	/* require an explicit show _after_ the custom-dialog signal fires */
	return dialog;
}
// GtkBuilder generated dialog, using fixed widgets to closely match
// the Windows layout, with some changes for color selector
GtkWidget * XAP_UnixDialog_FontChooser::constructWindowContents(GtkWidget *)
{
	GtkTreeSelection *selection;
	GtkWidget *vboxMain;
	GtkWidget *notebookMain;
	GtkWidget *labelFont;
	GtkWidget *labelStyle;
	GtkWidget *listFonts;
	GtkWidget *labelSize;
	GtkWidget *lblEffects;
	GtkWidget *grEffectRows;
	GtkWidget *checkbuttonStrikeout;
	GtkWidget *checkbuttonUnderline;
	GtkWidget *checkbuttonOverline;
	GtkWidget *checkbuttonHidden;
	GtkWidget *checkbuttonSubscript;
	GtkWidget *checkbuttonSuperscript;
 	GtkWidget *listStyles;
	GtkWidget *listSizes;
	GtkWidget *hbox1;
	GtkWidget *colorSelector;
	GtkWidget *colorBGSelector;
	GtkWidget *labelTabFont;
	GtkWidget *labelTabColor;
	GtkWidget *labelTabBGColor;
	GtkWidget *frame4;

	// the entry is a special drawing area full of one
	// of our graphics contexts
	GtkWidget *entryArea;

	const XAP_StringSet * pSS = m_pApp->getStringSet();

	vboxMain = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
	gtk_widget_show (vboxMain);

	notebookMain = gtk_notebook_new ();
	gtk_widget_show (notebookMain);
	gtk_box_pack_start (GTK_BOX (vboxMain), notebookMain, 1, 1, 0);
	gtk_container_set_border_width (GTK_CONTAINER (notebookMain), 8);

	GtkWidget *grid1;
	GtkWidget *scrolledwindow1;
	GtkWidget *scrolledwindow2;
	GtkWidget *scrolledwindow3;
//  	GtkWidget *hboxForEncoding;
	grid1 = gtk_grid_new();
	g_object_set(G_OBJECT(grid1),
	             "row-spacing", 6,
	             "column-spacing", 12,
	             "border-width", 12,
	             NULL);
	gtk_widget_show(grid1);

	std::string s;
	// Label for first page of the notebook
	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_FontTab,s);
	labelTabFont = gtk_label_new (s.c_str());
	gtk_widget_show (labelTabFont);
//
// Make first page of the notebook
//
	gtk_notebook_append_page(GTK_NOTEBOOK(notebookMain), grid1, labelTabFont);

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_FontLabel,s);
	labelFont = gtk_label_new (s.c_str());
	gtk_widget_set_halign(labelFont, GTK_ALIGN_CENTER);
	gtk_widget_show(labelFont);
	gtk_grid_attach(GTK_GRID(grid1), labelFont, 0, 0, 1, 1);

	scrolledwindow1 = gtk_scrolled_window_new(NULL, NULL);
	gtk_widget_show (scrolledwindow1);
	gtk_grid_attach(GTK_GRID(grid1), scrolledwindow1, 0, 1, 1, 3);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);

	listFonts = createFontTabTreeView();
	gtk_widget_show (listFonts);
	gtk_container_add (GTK_CONTAINER (scrolledwindow1), listFonts);

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_StyleLabel,s);
	labelStyle = gtk_label_new (s.c_str());
	gtk_widget_set_halign(labelStyle, GTK_ALIGN_CENTER);
	gtk_widget_show (labelStyle);
	gtk_grid_attach(GTK_GRID(grid1), labelStyle, 1, 0, 1, 1);

	scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL);
	gtk_widget_show (scrolledwindow2);
	gtk_grid_attach(GTK_GRID(grid1), scrolledwindow2, 1, 1, 1, 1);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_POLICY_NEVER, GTK_POLICY_NEVER);

	listStyles = createFontTabTreeView();
	gtk_widget_set_name (listStyles, "listStyles");
	gtk_widget_show (listStyles);
	gtk_container_add (GTK_CONTAINER (scrolledwindow2), listStyles);

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_SizeLabel,s);
	labelSize = gtk_label_new (s.c_str());
	gtk_widget_set_halign(labelSize, GTK_ALIGN_CENTER);
	gtk_widget_show (labelSize);
	gtk_grid_attach(GTK_GRID(grid1), labelSize, 2, 0, 1, 1);

	scrolledwindow3 = gtk_scrolled_window_new (NULL, NULL);
	gtk_widget_show (scrolledwindow3);
	gtk_grid_attach(GTK_GRID(grid1), scrolledwindow3, 2, 1, 1, 1);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow3), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);

	listSizes = createFontTabTreeView();
	gtk_widget_show (listSizes);
	gtk_container_add (GTK_CONTAINER (scrolledwindow3), listSizes);

	grEffectRows = gtk_grid_new();
	g_object_set(G_OBJECT(grEffectRows),
	             "row-spacing", 6,
	             "column-spacing", 12,
	             "margin-top", 12,
	             NULL);
	gtk_widget_show (grEffectRows);

	gtk_grid_attach(GTK_GRID(grid1), grEffectRows, 1, 2, 2, 1);
	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_EffectsFrameLabel,s);
	s = std::string("<b>") + s + "</b>";
	lblEffects = gtk_label_new (s.c_str());
	g_object_set(lblEffects, "use-markup", true, "xalign", 0., NULL);
	gtk_widget_show(lblEffects);
	gtk_grid_attach(GTK_GRID(grEffectRows), lblEffects, 0, 0, 4, 1);

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_StrikeoutCheck,s);
	checkbuttonStrikeout = gtk_check_button_new_with_label (s.c_str());
	gtk_widget_set_margin_start(checkbuttonStrikeout, 18);
	gtk_widget_show (checkbuttonStrikeout);
	gtk_grid_attach(GTK_GRID(grEffectRows), checkbuttonStrikeout, 0, 1, 1, 1);

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_UnderlineCheck,s);
	checkbuttonUnderline = gtk_check_button_new_with_label (s.c_str());
	gtk_widget_show (checkbuttonUnderline);
	gtk_grid_attach(GTK_GRID(grEffectRows), checkbuttonUnderline, 1, 1, 1, 1);

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_OverlineCheck,s);
	checkbuttonOverline = gtk_check_button_new_with_label (s.c_str());
	gtk_widget_show (checkbuttonOverline);
	gtk_grid_attach(GTK_GRID(grEffectRows), checkbuttonOverline, 2, 1, 1, 1);

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_HiddenCheck,s);
	checkbuttonHidden = gtk_check_button_new_with_label (s.c_str());
	gtk_widget_show (checkbuttonHidden);
	gtk_grid_attach(GTK_GRID(grEffectRows), checkbuttonHidden, 3, 1, 1, 1);

	/* subscript/superscript */

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_SubScript,s);
	checkbuttonSubscript = gtk_check_button_new_with_label (s.c_str());
	gtk_widget_set_margin_start(checkbuttonSubscript, 18);
	gtk_widget_show (checkbuttonSubscript);
	gtk_grid_attach(GTK_GRID(grEffectRows), checkbuttonSubscript, 0, 2, 1, 1);

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_SuperScript,s);
	checkbuttonSuperscript = gtk_check_button_new_with_label (s.c_str());
	gtk_widget_show (checkbuttonSuperscript);
	gtk_grid_attach(GTK_GRID(grEffectRows), checkbuttonSuperscript, 1, 2, 1, 1);

	/* Notebook page for ForeGround Color Selector */

	hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
	gtk_widget_show (hbox1);

    // Label for second page of the notebook

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_ColorTab,s);
	labelTabColor = gtk_label_new (s.c_str());
	gtk_widget_show (labelTabColor);

//
// Make second page of the notebook
//
    gtk_notebook_append_page(GTK_NOTEBOOK(notebookMain), hbox1,labelTabColor);

	colorSelector = gtk_color_chooser_widget_new ();
	gtk_container_set_border_width(GTK_CONTAINER(colorSelector), 6);
	gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(colorSelector), FALSE);
	gtk_widget_show (colorSelector);
	gtk_box_pack_start (GTK_BOX (hbox1), colorSelector, TRUE, TRUE, 0);

	/*Notebook page for Background Color Selector*/

	GtkWidget * vboxBG = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
	gtk_widget_show (vboxBG);

    // Label for third page of the notebook

	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_BGColorTab,s);
	labelTabBGColor = gtk_label_new (s.c_str());
	gtk_widget_show (labelTabBGColor);
//
// Make third page of the notebook
//
    gtk_notebook_append_page(GTK_NOTEBOOK(notebookMain), vboxBG,labelTabBGColor);

	colorBGSelector = gtk_color_chooser_widget_new ();
	gtk_container_set_border_width(GTK_CONTAINER(colorBGSelector), 6);
	gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(colorBGSelector), FALSE);
	gtk_widget_show (colorBGSelector);
	gtk_box_pack_start (GTK_BOX (vboxBG), colorBGSelector, TRUE, TRUE, 0);

//
// Make a toggle button to set hightlight color transparent
//
	pSS->getValueUTF8(XAP_STRING_ID_DLG_UFS_TransparencyCheck,s);
	GtkWidget * checkbuttonTrans = gtk_check_button_new_with_label (s.c_str());
	gtk_container_set_border_width(GTK_CONTAINER(checkbuttonTrans), 6);
	gtk_widget_show (checkbuttonTrans);
	gtk_box_pack_start (GTK_BOX (vboxBG), checkbuttonTrans, TRUE, TRUE, 0);

	/* frame with preview */

	frame4 = gtk_frame_new (NULL);
	gtk_frame_set_shadow_type(GTK_FRAME(frame4), GTK_SHADOW_NONE);
	gtk_widget_show (frame4);
	gtk_box_pack_start (GTK_BOX (vboxMain), frame4, FALSE, FALSE, PREVIEW_BOX_BORDER_WIDTH_PIXELS);
	// setting the height takes into account the border applied on all
	// sides, so we need to double the single border width
	gtk_widget_set_size_request (frame4, -1, PREVIEW_BOX_HEIGHT_PIXELS + (PREVIEW_BOX_BORDER_WIDTH_PIXELS * 2));
	gtk_container_set_border_width (GTK_CONTAINER (frame4), PREVIEW_BOX_BORDER_WIDTH_PIXELS);

	entryArea = gtk_drawing_area_new();
	gtk_widget_set_events(entryArea, GDK_EXPOSURE_MASK);
	g_signal_connect(G_OBJECT(entryArea), "draw",
					   G_CALLBACK(s_drawing_area_draw), NULL);
	gtk_widget_set_size_request (entryArea, -1, PREVIEW_BOX_HEIGHT_PIXELS);
	gtk_widget_show (entryArea);
	gtk_container_add (GTK_CONTAINER (frame4), entryArea);


	// save out to members for callback and class access
	m_fontList = listFonts;
	m_styleList = listStyles;
	m_sizeList = listSizes;
	m_colorSelector = colorSelector;
	m_bgcolorSelector = colorBGSelector;
	m_preview = entryArea;
	m_checkStrikeOut = checkbuttonStrikeout;
	m_checkUnderline = checkbuttonUnderline;
	m_checkOverline = checkbuttonOverline;
	m_checkSubScript = checkbuttonSubscript;
	m_checkSuperScript = checkbuttonSuperscript;
	m_checkHidden = checkbuttonHidden;
	m_checkTransparency = checkbuttonTrans;

	// bind signals to things
	g_signal_connect(G_OBJECT(m_checkUnderline),
					   "toggled",
					   G_CALLBACK(s_underline_toggled),
					   static_cast<gpointer>(this));

	g_signal_connect(G_OBJECT(m_checkOverline),
					   "toggled",
					   G_CALLBACK(s_overline_toggled),
					   static_cast<gpointer>(this));

	g_signal_connect(G_OBJECT(m_checkStrikeOut),
					   "toggled",
					   G_CALLBACK(s_strikeout_toggled),
					   static_cast<gpointer>(this));

	g_signal_connect(G_OBJECT(m_checkHidden),
					   "toggled",
					   G_CALLBACK(s_hidden_toggled),
					   static_cast<gpointer>(this));

	m_iSubScriptId = g_signal_connect(G_OBJECT(m_checkSubScript),
					   "toggled",
					   G_CALLBACK(s_subscript_toggled),
					   static_cast<gpointer>(this));

	m_iSuperScriptId = g_signal_connect(G_OBJECT(m_checkSuperScript),
					   "toggled",
					   G_CALLBACK(s_superscript_toggled),
					   static_cast<gpointer>(this));

	g_signal_connect(G_OBJECT(m_checkTransparency),
					   "toggled",
					   G_CALLBACK(s_transparency_toggled),
					   static_cast<gpointer>(this));

	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listFonts));
	g_signal_connect(G_OBJECT(selection),
					   "changed",
					   G_CALLBACK(s_select_row_font),
					   static_cast<gpointer>(this));
	selection = NULL;

	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listStyles));
	g_signal_connect(G_OBJECT(selection),
					   "changed",
					   G_CALLBACK(s_select_row_style),
					   static_cast<gpointer>(this));
	selection = NULL;

	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listSizes));
	g_signal_connect(G_OBJECT(selection),
					   "changed",
					   G_CALLBACK(s_select_row_size),
					   static_cast<gpointer>(this));
	selection = NULL;

	// This is a catch-all color selector callback which catches any
	// real-time updating of the color so we can refresh our preview
	// text
	g_signal_connect(G_OBJECT(colorSelector),
#if GTK_CHECK_VERSION(3,4,0)
			 "color-activated",
#else
			 "color-changed", //"event",
#endif
			 G_CALLBACK(s_color_update),
			 static_cast<gpointer>(this));

	g_signal_connect(G_OBJECT(colorBGSelector),
#if GTK_CHECK_VERSION(3,4,0)
			 "color-activated",
#else
			 "color-changed", //"event",
#endif
			 G_CALLBACK(s_bgcolor_update),
			 static_cast<gpointer>(this));

	gtk_widget_set_can_focus(listFonts, true);
	gtk_widget_set_can_focus(listStyles, true);
	gtk_widget_set_can_focus(listSizes, true);

	// Make the tab focus list more sensible
	// font -> syle -> size -> other options ...
	GList* focusList = NULL;

	focusList = g_list_append(focusList, scrolledwindow1);
	focusList = g_list_append(focusList, scrolledwindow2);
	focusList = g_list_append(focusList, scrolledwindow3);
	focusList = g_list_append(focusList, grEffectRows);
	gtk_container_set_focus_chain(GTK_CONTAINER(grid1), focusList);
	g_list_free(focusList);
	gtk_widget_grab_focus(scrolledwindow1);

	
	const gchar * text;
	GtkTreeModel* model;
	GtkTreeIter iter;

	// update the styles list
	model = gtk_tree_view_get_model(GTK_TREE_VIEW(m_styleList));
	gtk_list_store_clear(GTK_LIST_STORE(model));
	
	text = pSS->getValue(XAP_STRING_ID_DLG_UFS_StyleRegular); 
	gtk_list_store_append(GTK_LIST_STORE(model), &iter);
	gtk_list_store_set(GTK_LIST_STORE(model), &iter, TEXT_COLUMN, text, -1);
	text = pSS->getValue(XAP_STRING_ID_DLG_UFS_StyleItalic);
	gtk_list_store_append(GTK_LIST_STORE(model), &iter);
	gtk_list_store_set(GTK_LIST_STORE(model), &iter, TEXT_COLUMN, text, -1);
	text = pSS->getValue(XAP_STRING_ID_DLG_UFS_StyleBold);
	gtk_list_store_append(GTK_LIST_STORE(model), &iter);
	gtk_list_store_set(GTK_LIST_STORE(model), &iter, TEXT_COLUMN, text, -1);
	text = pSS->getValue(XAP_STRING_ID_DLG_UFS_StyleBoldItalic);  
	gtk_list_store_append(GTK_LIST_STORE(model), &iter);
	gtk_list_store_set(GTK_LIST_STORE(model), &iter, TEXT_COLUMN, text, -1);



	model = gtk_tree_view_get_model(GTK_TREE_VIEW(m_sizeList));
	gtk_list_store_clear(GTK_LIST_STORE(model));
	// TODO perhaps populate the list based on the selected font/style?
	{
		int sz = XAP_EncodingManager::fontsizes_mapping.size();
		for (int i = 0; i < sz; ++i)
		{
			text = XAP_EncodingManager::fontsizes_mapping.nth2(i);
			gtk_list_store_append(GTK_LIST_STORE(model), &iter);
			gtk_list_store_set(GTK_LIST_STORE(model), &iter, TEXT_COLUMN, text, -1);
	    }
	}

	return vboxMain;
}
示例#4
0
文件: prop-editor.c 项目: 3v1n0/gtk
static GtkWidget *
property_editor (GObject                *object,
                 GParamSpec             *spec,
                 GtkInspectorPropEditor *editor)
{
  GtkWidget *prop_edit;
  GtkAdjustment *adj;
  gchar *msg;
  GType type = G_PARAM_SPEC_TYPE (spec);

  if (type == G_TYPE_PARAM_INT)
    {
      adj = gtk_adjustment_new (G_PARAM_SPEC_INT (spec)->default_value,
                                G_PARAM_SPEC_INT (spec)->minimum,
                                G_PARAM_SPEC_INT (spec)->maximum,
                                1,
                                MAX ((G_PARAM_SPEC_INT (spec)->maximum - G_PARAM_SPEC_INT (spec)->minimum) / 10, 1),
                                0.0);

      prop_edit = gtk_spin_button_new (adj, 1.0, 0);

      g_object_connect_property (object, spec, G_CALLBACK (int_changed), adj, G_OBJECT (adj)); 

      connect_controller (G_OBJECT (adj), "value_changed",
                          object, spec, G_CALLBACK (int_modified));
    }
  else if (type == G_TYPE_PARAM_UINT)
    {
      adj = gtk_adjustment_new (G_PARAM_SPEC_UINT (spec)->default_value,
                                G_PARAM_SPEC_UINT (spec)->minimum,
                                G_PARAM_SPEC_UINT (spec)->maximum,
                                1,
                                MAX ((G_PARAM_SPEC_UINT (spec)->maximum - G_PARAM_SPEC_UINT (spec)->minimum) / 10, 1),
                                0.0);

      prop_edit = gtk_spin_button_new (adj, 1.0, 0);

      g_object_connect_property (object, spec,
                                 G_CALLBACK (uint_changed),
                                 adj, G_OBJECT (adj));

      connect_controller (G_OBJECT (adj), "value_changed",
                          object, spec, G_CALLBACK (uint_modified));
    }
  else if (type == G_TYPE_PARAM_FLOAT)
    {
      adj = gtk_adjustment_new (G_PARAM_SPEC_FLOAT (spec)->default_value,
                                G_PARAM_SPEC_FLOAT (spec)->minimum,
                                G_PARAM_SPEC_FLOAT (spec)->maximum,
                                0.1,
                                MAX ((G_PARAM_SPEC_FLOAT (spec)->maximum - G_PARAM_SPEC_FLOAT (spec)->minimum) / 10, 0.1),
                                0.0);

      prop_edit = gtk_spin_button_new (adj, 0.1, 2);

      g_object_connect_property (object, spec,
                                 G_CALLBACK (float_changed),
                                 adj, G_OBJECT (adj));

      connect_controller (G_OBJECT (adj), "value_changed",
                          object, spec, G_CALLBACK (float_modified));
    }
  else if (type == G_TYPE_PARAM_DOUBLE)
    {
      adj = gtk_adjustment_new (G_PARAM_SPEC_DOUBLE (spec)->default_value,
                                G_PARAM_SPEC_DOUBLE (spec)->minimum,
                                G_PARAM_SPEC_DOUBLE (spec)->maximum,
                                0.1,
                                MAX ((G_PARAM_SPEC_DOUBLE (spec)->maximum - G_PARAM_SPEC_DOUBLE (spec)->minimum) / 10, 0.1),
                                0.0);

      prop_edit = gtk_spin_button_new (adj, 0.1, 2);

      g_object_connect_property (object, spec,
                                 G_CALLBACK (double_changed),
                                 adj, G_OBJECT (adj));

      connect_controller (G_OBJECT (adj), "value_changed",
                          object, spec, G_CALLBACK (double_modified));
    }
  else if (type == G_TYPE_PARAM_STRING)
    {
      prop_edit = gtk_entry_new ();

      g_object_connect_property (object, spec,
                                 G_CALLBACK (string_changed),
                                 prop_edit, G_OBJECT (prop_edit));

      connect_controller (G_OBJECT (prop_edit), "changed",
                          object, spec, G_CALLBACK (string_modified));
    }
  else if (type == G_TYPE_PARAM_BOOLEAN)
    {
      prop_edit = gtk_toggle_button_new_with_label ("");

      g_object_connect_property (object, spec,
                                 G_CALLBACK (bool_changed),
                                 prop_edit, G_OBJECT (prop_edit));

      connect_controller (G_OBJECT (prop_edit), "toggled",
                          object, spec, G_CALLBACK (bool_modified));
    }
  else if (type == G_TYPE_PARAM_ENUM)
    {
      {
        GtkWidget *box;
        GEnumClass *eclass;
        GtkWidget *first;
        gint j;

        prop_edit = gtk_scrolled_window_new (NULL, NULL);
        g_object_set (prop_edit,
                      "expand", TRUE,
                      "hscrollbar-policy", GTK_POLICY_NEVER,
                      "vscrollbar-policy", GTK_POLICY_NEVER,
                      NULL);
        box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
        gtk_widget_show (box);
        gtk_container_add (GTK_CONTAINER (prop_edit), box);

        eclass = G_ENUM_CLASS (g_type_class_ref (spec->value_type));

        j = 0;
        first = NULL;
        while (j < eclass->n_values)
          {
            GtkWidget *b;

            b = gtk_radio_button_new_with_label_from_widget ((GtkRadioButton*)first, eclass->values[j].value_name);
            if (first == NULL)
              first = b;
            g_object_set_data (G_OBJECT (b), "index", GINT_TO_POINTER (j));
            gtk_widget_show (b);
            gtk_box_pack_start (GTK_BOX (box), b, FALSE, FALSE, 0);
            connect_controller (G_OBJECT (b), "toggled",
                                object, spec, G_CALLBACK (enum_modified));
            ++j;
          }

        if (j >= 10)
          g_object_set (prop_edit, "vscrollbar-policy", GTK_POLICY_AUTOMATIC, NULL);

        g_type_class_unref (eclass);

        g_object_connect_property (object, spec,
                                   G_CALLBACK (enum_changed),
                                   prop_edit, G_OBJECT (prop_edit));
      }
    }
  else if (type == G_TYPE_PARAM_FLAGS)
    {
      {
        GtkWidget *box;
        GFlagsClass *fclass;
        gint j;

        prop_edit = gtk_scrolled_window_new (NULL, NULL);
        g_object_set (prop_edit,
                      "expand", TRUE,
                      "hscrollbar-policy", GTK_POLICY_NEVER,
                      "vscrollbar-policy", GTK_POLICY_NEVER,
                      NULL);
        box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
        gtk_widget_show (box);
        gtk_container_add (GTK_CONTAINER (prop_edit), box);

        fclass = G_FLAGS_CLASS (g_type_class_ref (spec->value_type));

        for (j = 0; j < fclass->n_values; j++)
          {
            GtkWidget *b;

            b = gtk_check_button_new_with_label (fclass->values[j].value_name);
            g_object_set_data (G_OBJECT (b), "index", GINT_TO_POINTER (j));
            gtk_widget_show (b);
            gtk_box_pack_start (GTK_BOX (box), b, FALSE, FALSE, 0);
            connect_controller (G_OBJECT (b), "toggled",
                                object, spec, G_CALLBACK (flags_modified));
          }

        if (j >= 10)
          g_object_set (prop_edit, "vscrollbar-policy", GTK_POLICY_AUTOMATIC, NULL);

        g_type_class_unref (fclass);

        g_object_connect_property (object, spec,
                                   G_CALLBACK (flags_changed),
                                   prop_edit, G_OBJECT (prop_edit));
      }
    }
  else if (type == G_TYPE_PARAM_UNICHAR)
    {
      prop_edit = gtk_entry_new ();
      gtk_entry_set_max_length (GTK_ENTRY (prop_edit), 1);

      g_object_connect_property (object, spec,
                                 G_CALLBACK (unichar_changed),
                                 prop_edit, G_OBJECT (prop_edit));

      connect_controller (G_OBJECT (prop_edit), "changed",
                          object, spec, G_CALLBACK (unichar_modified));
    }
  else if (type == G_TYPE_PARAM_POINTER)
    {
      prop_edit = gtk_label_new ("");

      g_object_connect_property (object, spec,
                                 G_CALLBACK (pointer_changed),
                                 prop_edit, G_OBJECT (prop_edit));
    }
  else if (type == G_TYPE_PARAM_OBJECT)
    {
      GtkWidget *label, *button;

      prop_edit = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);

      label = gtk_label_new ("");
      button = gtk_button_new_with_label (_("Properties"));
      g_signal_connect_swapped (button, "clicked",
                                G_CALLBACK (object_properties),
                                editor);
      gtk_container_add (GTK_CONTAINER (prop_edit), label);
      gtk_container_add (GTK_CONTAINER (prop_edit), button);
      gtk_widget_show (label);
      gtk_widget_show (button);

      g_object_connect_property (object, spec,
                                 G_CALLBACK (object_changed),
                                 prop_edit, G_OBJECT (label));
    }
  else if (type == G_TYPE_PARAM_BOXED &&
           G_PARAM_SPEC_VALUE_TYPE (spec) == GDK_TYPE_RGBA)
    {
      prop_edit = gtk_color_chooser_widget_new ();
      gtk_color_chooser_set_use_alpha (GTK_COLOR_CHOOSER (prop_edit), TRUE);

      g_object_connect_property (object, spec,
                                 G_CALLBACK (rgba_changed),
                                 prop_edit, G_OBJECT (prop_edit));

      connect_controller (G_OBJECT (prop_edit), "notify::rgba",
                          object, spec, G_CALLBACK (rgba_modified));
    }
  else if (type == G_TYPE_PARAM_BOXED &&
           G_PARAM_SPEC_VALUE_TYPE (spec) == g_type_from_name ("GdkColor"))
    {
      prop_edit = gtk_color_chooser_widget_new ();
      gtk_color_chooser_set_use_alpha (GTK_COLOR_CHOOSER (prop_edit), FALSE);

      g_object_connect_property (object, spec,
                                 G_CALLBACK (color_changed),
                                 prop_edit, G_OBJECT (prop_edit));

      connect_controller (G_OBJECT (prop_edit), "notify::rgba",
                          object, spec, G_CALLBACK (color_modified));
    }
  else if (type == G_TYPE_PARAM_BOXED &&
           G_PARAM_SPEC_VALUE_TYPE (spec) == PANGO_TYPE_FONT_DESCRIPTION)
    {
      prop_edit = gtk_font_chooser_widget_new ();

      g_object_connect_property (object, spec,
                                 G_CALLBACK (font_changed),
                                 prop_edit, G_OBJECT (prop_edit));

      connect_controller (G_OBJECT (prop_edit), "notify::font-desc",
                          object, spec, G_CALLBACK (font_modified));
    }
  else
    {
      msg = g_strdup_printf (_("Uneditable property type: %s"),
                             g_type_name (G_PARAM_SPEC_TYPE (spec)));
      prop_edit = gtk_label_new (msg);
      g_free (msg);
      gtk_widget_set_halign (prop_edit, GTK_ALIGN_START);
      gtk_widget_set_valign (prop_edit, GTK_ALIGN_CENTER);
    }

  if (g_param_spec_get_blurb (spec))
    gtk_widget_set_tooltip_text (prop_edit, g_param_spec_get_blurb (spec));

  notify_property (object, spec);

  return prop_edit;
}