2006-09-05 14:24:47 +00:00
|
|
|
/*
|
|
|
|
* ui_utils.c - this file is part of Geany, a fast and lightweight IDE
|
|
|
|
*
|
2010-01-01 22:55:18 +00:00
|
|
|
* Copyright 2006-2010 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
|
|
|
* Copyright 2006-2010 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
|
2006-09-05 14:24:47 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
*/
|
|
|
|
|
2008-12-28 17:25:09 +00:00
|
|
|
/** @file ui_utils.h
|
2007-02-24 11:41:56 +00:00
|
|
|
* User Interface general utility functions.
|
|
|
|
*/
|
2006-09-05 14:24:47 +00:00
|
|
|
|
|
|
|
#include "geany.h"
|
|
|
|
|
|
|
|
#include <string.h>
|
2010-05-10 17:21:13 +00:00
|
|
|
#include <ctype.h>
|
2010-03-07 19:33:15 +00:00
|
|
|
#include <gdk/gdkkeysyms.h>
|
2006-09-05 14:24:47 +00:00
|
|
|
|
|
|
|
#include "ui_utils.h"
|
2007-08-23 11:34:06 +00:00
|
|
|
#include "prefs.h"
|
2006-09-05 14:24:47 +00:00
|
|
|
#include "sciwrappers.h"
|
|
|
|
#include "document.h"
|
2008-06-02 15:31:59 +00:00
|
|
|
#include "documentprivate.h"
|
2007-08-15 15:37:21 +00:00
|
|
|
#include "filetypes.h"
|
2006-09-05 14:24:47 +00:00
|
|
|
#include "support.h"
|
|
|
|
#include "msgwindow.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "callbacks.h"
|
|
|
|
#include "encodings.h"
|
|
|
|
#include "images.c"
|
2009-09-28 11:16:59 +00:00
|
|
|
#include "sidebar.h"
|
2007-05-26 09:02:37 +00:00
|
|
|
#include "win32.h"
|
2007-05-28 15:24:21 +00:00
|
|
|
#include "project.h"
|
2007-05-29 16:30:54 +00:00
|
|
|
#include "editor.h"
|
2007-07-23 15:41:08 +00:00
|
|
|
#include "plugins.h"
|
2008-07-08 16:30:37 +00:00
|
|
|
#include "symbols.h"
|
2008-12-06 11:10:06 +00:00
|
|
|
#include "toolbar.h"
|
2009-06-20 16:51:32 +00:00
|
|
|
#include "geanymenubuttonaction.h"
|
2010-06-17 12:35:17 +00:00
|
|
|
#include "main.h"
|
2010-07-09 17:15:16 +00:00
|
|
|
#include "stash.h"
|
|
|
|
#include "keyfile.h"
|
2006-09-05 14:24:47 +00:00
|
|
|
|
|
|
|
|
2008-05-16 12:08:39 +00:00
|
|
|
GeanyInterfacePrefs interface_prefs;
|
2008-05-22 14:41:28 +00:00
|
|
|
GeanyMainWidgets main_widgets;
|
|
|
|
|
2007-08-23 11:34:06 +00:00
|
|
|
UIPrefs ui_prefs;
|
|
|
|
UIWidgets ui_widgets;
|
|
|
|
|
2007-07-20 12:06:51 +00:00
|
|
|
static struct
|
|
|
|
{
|
2009-06-20 16:51:32 +00:00
|
|
|
/* pointers to widgets only sensitive when there is at least one document, the pointers can
|
|
|
|
* also be GtkAction objects, so check each pointer before using it */
|
2008-07-17 16:28:16 +00:00
|
|
|
GPtrArray *document_buttons;
|
|
|
|
GtkWidget *menu_insert_include_items[2];
|
2008-07-25 11:23:52 +00:00
|
|
|
GtkWidget *popup_goto_items[4];
|
2008-07-17 16:28:16 +00:00
|
|
|
GtkWidget *popup_copy_items[3];
|
|
|
|
GtkWidget *menu_copy_items[3];
|
|
|
|
GtkWidget *redo_items[3];
|
|
|
|
GtkWidget *undo_items[3];
|
|
|
|
GtkWidget *save_buttons[4];
|
2008-11-26 13:15:53 +00:00
|
|
|
GtkWidget *config_files_menu;
|
2009-10-27 17:27:24 +00:00
|
|
|
GtkWidget *commands_menu;
|
2009-10-27 18:10:39 +00:00
|
|
|
GtkWidget *format_menu;
|
2007-07-20 12:06:51 +00:00
|
|
|
}
|
|
|
|
widgets;
|
|
|
|
|
2009-04-07 22:09:23 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
RECENT_FILE_FILE,
|
|
|
|
RECENT_FILE_PROJECT
|
|
|
|
};
|
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2009-04-07 22:09:23 +00:00
|
|
|
gint type;
|
2009-04-05 14:14:29 +00:00
|
|
|
GQueue *recent_queue;
|
|
|
|
GtkWidget *menubar;
|
|
|
|
GtkWidget *toolbar;
|
|
|
|
void (*activate_cb)(GtkMenuItem *, gpointer);
|
|
|
|
} GeanyRecentFiles;
|
|
|
|
|
2007-07-20 12:06:51 +00:00
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
static void update_recent_menu(GeanyRecentFiles *grf);
|
|
|
|
static void recent_file_loaded(const gchar *utf8_filename, GeanyRecentFiles *grf);
|
2008-12-06 11:10:06 +00:00
|
|
|
static void recent_file_activate_cb(GtkMenuItem *menuitem, gpointer user_data);
|
2009-04-05 14:14:29 +00:00
|
|
|
static void recent_project_activate_cb(GtkMenuItem *menuitem, gpointer user_data);
|
2009-01-27 20:19:43 +00:00
|
|
|
static GtkWidget *progress_bar_create(void);
|
2008-12-06 11:10:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* simple wrapper for gtk_widget_set_sensitive() to allow widget being NULL */
|
|
|
|
void ui_widget_set_sensitive(GtkWidget *widget, gboolean set)
|
|
|
|
{
|
2009-04-15 22:47:33 +00:00
|
|
|
if (widget != NULL)
|
2008-12-06 11:10:06 +00:00
|
|
|
gtk_widget_set_sensitive(widget, set);
|
|
|
|
}
|
2006-09-05 14:24:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* allow_override is TRUE if text can be ignored when another message has been set
|
|
|
|
* that didn't use allow_override and has not timed out. */
|
2006-11-25 16:33:38 +00:00
|
|
|
static void set_statusbar(const gchar *text, gboolean allow_override)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
static glong last_time = 0;
|
|
|
|
GTimeVal timeval;
|
|
|
|
const gint GEANY_STATUS_TIMEOUT = 1;
|
|
|
|
|
2008-05-16 12:08:39 +00:00
|
|
|
if (! interface_prefs.statusbar_visible)
|
2008-02-27 13:17:29 +00:00
|
|
|
return; /* just do nothing if statusbar is not visible */
|
2007-10-24 10:52:48 +00:00
|
|
|
|
2006-09-05 14:24:47 +00:00
|
|
|
g_get_current_time(&timeval);
|
|
|
|
|
|
|
|
if (! allow_override)
|
|
|
|
{
|
2008-05-22 14:41:28 +00:00
|
|
|
gtk_statusbar_pop(GTK_STATUSBAR(ui_widgets.statusbar), 1);
|
|
|
|
gtk_statusbar_push(GTK_STATUSBAR(ui_widgets.statusbar), 1, text);
|
2006-09-05 14:24:47 +00:00
|
|
|
last_time = timeval.tv_sec;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (timeval.tv_sec > last_time + GEANY_STATUS_TIMEOUT)
|
|
|
|
{
|
2008-05-22 14:41:28 +00:00
|
|
|
gtk_statusbar_pop(GTK_STATUSBAR(ui_widgets.statusbar), 1);
|
|
|
|
gtk_statusbar_push(GTK_STATUSBAR(ui_widgets.statusbar), 1, text);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-12 18:15:48 +00:00
|
|
|
/** Displays text on the statusbar.
|
2008-07-24 12:01:30 +00:00
|
|
|
* @param log Whether the message should be recorded in the Status window.
|
|
|
|
* @param format A @c printf -style string. */
|
2007-10-24 10:52:48 +00:00
|
|
|
void ui_set_statusbar(gboolean log, const gchar *format, ...)
|
2006-11-25 16:33:38 +00:00
|
|
|
{
|
2010-04-25 17:42:01 +00:00
|
|
|
gchar *string;
|
2006-11-25 16:33:38 +00:00
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, format);
|
2010-04-25 17:42:01 +00:00
|
|
|
string = g_strdup_vprintf(format, args);
|
2006-11-25 16:33:38 +00:00
|
|
|
va_end(args);
|
|
|
|
|
2007-10-24 10:52:48 +00:00
|
|
|
if (! prefs.suppress_status_messages)
|
2007-08-05 11:03:44 +00:00
|
|
|
set_statusbar(string, FALSE);
|
2007-10-24 10:52:48 +00:00
|
|
|
|
|
|
|
if (log || prefs.suppress_status_messages)
|
|
|
|
msgwin_status_add("%s", string);
|
2010-04-25 17:42:01 +00:00
|
|
|
|
|
|
|
g_free(string);
|
2006-11-25 16:33:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-29 12:11:21 +00:00
|
|
|
static gchar *statusbar_template = NULL;
|
|
|
|
|
|
|
|
/* note: some comments below are for translators */
|
|
|
|
static void add_statusbar_statistics(GString *stats_str,
|
|
|
|
GeanyDocument *doc, guint line, guint col)
|
|
|
|
{
|
|
|
|
const gchar *cur_tag;
|
|
|
|
const gchar *fmt;
|
|
|
|
const gchar *expos; /* % expansion position */
|
|
|
|
const gchar sp[] = " ";
|
|
|
|
|
2010-07-08 11:35:32 +00:00
|
|
|
fmt = NZV(statusbar_template) ? statusbar_template :
|
2010-06-29 12:11:21 +00:00
|
|
|
/* Status bar statistics: col = column, sel = selection. */
|
|
|
|
_("line: %l / %L\t col: %c\t sel: %s\t %w %t %m"
|
|
|
|
"mode: %M encoding: %e filetype: %f scope: %S");
|
|
|
|
|
|
|
|
g_string_assign(stats_str, "");
|
|
|
|
while ((expos = strchr(fmt, '%')) != NULL)
|
|
|
|
{
|
|
|
|
/* append leading text before % char */
|
|
|
|
g_string_append_len(stats_str, fmt, expos - fmt);
|
|
|
|
|
|
|
|
switch (*++expos)
|
|
|
|
{
|
|
|
|
case 'l':
|
|
|
|
g_string_append_printf(stats_str, "%d", line + 1);
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
g_string_append_printf(stats_str, "%d",
|
|
|
|
sci_get_line_count(doc->editor->sci));
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
g_string_append_printf(stats_str, "%d", col);
|
|
|
|
break;
|
|
|
|
case 'C':
|
|
|
|
g_string_append_printf(stats_str, "%d", col + 1);
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
g_string_append_printf(stats_str, "%d",
|
|
|
|
sci_get_selected_text_length(doc->editor->sci) - 1);
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
/* RO = read-only */
|
|
|
|
g_string_append(stats_str, (doc->readonly) ? _("RO ") :
|
|
|
|
/* OVR = overwrite/overtype, INS = insert */
|
|
|
|
(sci_get_overtype(doc->editor->sci) ? _("OVR") : _("INS")));
|
|
|
|
break;
|
|
|
|
case 'r':
|
2010-06-29 15:44:41 +00:00
|
|
|
if (doc->readonly)
|
|
|
|
{
|
|
|
|
g_string_append(stats_str, _("RO ")); /* RO = read-only */
|
|
|
|
g_string_append(stats_str, sp + 1);
|
|
|
|
}
|
2010-06-29 12:11:21 +00:00
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
{
|
|
|
|
switch (editor_get_indent_prefs(doc->editor)->type)
|
|
|
|
{
|
|
|
|
case GEANY_INDENT_TYPE_TABS:
|
|
|
|
g_string_append(stats_str, _("TAB"));
|
|
|
|
break;
|
|
|
|
case GEANY_INDENT_TYPE_SPACES: /* SP = space */
|
|
|
|
g_string_append(stats_str, _("SP"));
|
|
|
|
break;
|
|
|
|
case GEANY_INDENT_TYPE_BOTH: /* T/S = tabs and spaces */
|
|
|
|
g_string_append(stats_str, _("T/S"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'm':
|
|
|
|
if (doc->changed)
|
|
|
|
{
|
2010-06-29 15:44:41 +00:00
|
|
|
g_string_append(stats_str, _("MOD")); /* MOD = modified */
|
2010-06-29 12:11:21 +00:00
|
|
|
g_string_append(stats_str, sp);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
g_string_append(stats_str, editor_get_eol_char_name(doc->editor));
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
g_string_append(stats_str,
|
|
|
|
doc->encoding ? doc->encoding : _("unknown"));
|
|
|
|
if (encodings_is_unicode_charset(doc->encoding) && (doc->has_bom))
|
2010-06-29 15:44:41 +00:00
|
|
|
{
|
|
|
|
g_string_append_c(stats_str, ' ');
|
2010-06-29 12:11:21 +00:00
|
|
|
g_string_append(stats_str, _("(with BOM)")); /* BOM = byte order mark */
|
2010-06-29 15:44:41 +00:00
|
|
|
}
|
2010-06-29 12:11:21 +00:00
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
g_string_append(stats_str, doc->file_type->name);
|
|
|
|
break;
|
|
|
|
case 'S':
|
|
|
|
symbols_get_current_function(doc, &cur_tag);
|
|
|
|
g_string_append(stats_str, cur_tag);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_string_append_len(stats_str, expos, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip past %c chars */
|
|
|
|
if (*expos)
|
|
|
|
fmt = expos + 1;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* add any remaining text */
|
|
|
|
g_string_append(stats_str, fmt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-25 16:33:38 +00:00
|
|
|
/* updates the status bar document statistics */
|
2008-06-15 13:35:48 +00:00
|
|
|
void ui_update_statusbar(GeanyDocument *doc, gint pos)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-05-16 12:08:39 +00:00
|
|
|
if (! interface_prefs.statusbar_visible)
|
2008-02-27 13:17:29 +00:00
|
|
|
return; /* just do nothing if statusbar is not visible */
|
2007-04-10 17:06:57 +00:00
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
if (doc == NULL)
|
2008-06-15 13:35:48 +00:00
|
|
|
doc = document_get_current();
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
if (doc != NULL)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2007-10-17 12:27:07 +00:00
|
|
|
static GString *stats_str = NULL;
|
|
|
|
guint line, col;
|
|
|
|
|
2009-04-05 21:07:40 +00:00
|
|
|
if (G_UNLIKELY(stats_str == NULL))
|
2007-10-17 12:27:07 +00:00
|
|
|
stats_str = g_string_sized_new(120);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2009-04-05 21:07:40 +00:00
|
|
|
if (pos == -1)
|
|
|
|
pos = sci_get_current_position(doc->editor->sci);
|
2008-07-14 11:13:54 +00:00
|
|
|
line = sci_get_line_from_position(doc->editor->sci, pos);
|
2006-10-28 16:25:17 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* Add temporary fix for sci infinite loop in Document::GetColumn(int)
|
|
|
|
* when current pos is beyond document end (can occur when removing
|
|
|
|
* blocks of selected lines especially esp. brace sections near end of file). */
|
2008-07-14 11:13:54 +00:00
|
|
|
if (pos <= sci_get_length(doc->editor->sci))
|
|
|
|
col = sci_get_col_from_position(doc->editor->sci, pos);
|
2006-10-28 16:25:17 +00:00
|
|
|
else
|
|
|
|
col = 0;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2010-06-29 12:11:21 +00:00
|
|
|
add_statusbar_statistics(stats_str, doc, line, col);
|
2007-10-17 12:27:07 +00:00
|
|
|
|
2008-06-06 14:17:16 +00:00
|
|
|
#ifdef GEANY_DEBUG
|
2010-06-29 12:11:21 +00:00
|
|
|
{
|
|
|
|
const gchar sp[] = " ";
|
2008-06-06 14:17:16 +00:00
|
|
|
g_string_append(stats_str, sp);
|
2008-09-18 13:25:13 +00:00
|
|
|
g_string_append_printf(stats_str, "pos: %d", pos);
|
|
|
|
g_string_append(stats_str, sp);
|
|
|
|
g_string_append_printf(stats_str, "style: %d", sci_get_style_at(doc->editor->sci, pos));
|
2010-06-29 12:11:21 +00:00
|
|
|
}
|
2008-06-06 14:17:16 +00:00
|
|
|
#endif
|
2008-02-27 13:17:29 +00:00
|
|
|
/* can be overridden by status messages */
|
|
|
|
set_statusbar(stats_str->str, TRUE);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
2008-02-27 13:17:29 +00:00
|
|
|
else /* no documents */
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-02-27 13:17:29 +00:00
|
|
|
set_statusbar("", TRUE); /* can be overridden by status messages */
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* This sets the window title according to the current filename. */
|
2008-06-15 13:35:48 +00:00
|
|
|
void ui_set_window_title(GeanyDocument *doc)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2007-05-28 15:24:21 +00:00
|
|
|
GString *str;
|
|
|
|
GeanyProject *project = app->project;
|
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
if (doc == NULL)
|
|
|
|
doc = document_get_current();
|
2007-05-28 15:24:21 +00:00
|
|
|
|
|
|
|
str = g_string_new(NULL);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
if (doc != NULL)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-06-15 13:35:48 +00:00
|
|
|
g_string_append(str, doc->changed ? "*" : "");
|
2007-05-28 15:24:21 +00:00
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
if (doc->file_name == NULL)
|
2008-06-15 13:35:48 +00:00
|
|
|
g_string_append(str, DOC_FILENAME(doc));
|
2007-02-01 17:07:52 +00:00
|
|
|
else
|
|
|
|
{
|
2009-04-21 20:53:23 +00:00
|
|
|
gchar *short_name = document_get_basename_for_display(doc, 30);
|
2008-06-15 13:35:48 +00:00
|
|
|
gchar *dirname = g_path_get_dirname(DOC_FILENAME(doc));
|
2007-02-01 17:07:52 +00:00
|
|
|
|
2009-04-21 20:53:23 +00:00
|
|
|
g_string_append(str, short_name);
|
2007-05-28 15:24:21 +00:00
|
|
|
g_string_append(str, " - ");
|
|
|
|
g_string_append(str, dirname ? dirname : "");
|
2009-04-21 20:53:23 +00:00
|
|
|
g_free(short_name);
|
2007-02-01 17:07:52 +00:00
|
|
|
g_free(dirname);
|
|
|
|
}
|
2007-05-28 15:24:21 +00:00
|
|
|
g_string_append(str, " - ");
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
2007-05-28 15:24:21 +00:00
|
|
|
if (project)
|
|
|
|
{
|
|
|
|
g_string_append_c(str, '[');
|
|
|
|
g_string_append(str, project->name);
|
|
|
|
g_string_append(str, "] - ");
|
|
|
|
}
|
|
|
|
g_string_append(str, "Geany");
|
2010-06-17 12:35:17 +00:00
|
|
|
if (cl_options.new_instance)
|
|
|
|
{
|
|
|
|
g_string_append(str, _(" (new instance)"));
|
|
|
|
}
|
2008-05-22 14:41:28 +00:00
|
|
|
gtk_window_set_title(GTK_WINDOW(main_widgets.window), str->str);
|
2007-05-28 15:24:21 +00:00
|
|
|
g_string_free(str, TRUE);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ui_set_editor_font(const gchar *font_name)
|
|
|
|
{
|
2006-10-09 16:08:53 +00:00
|
|
|
guint i;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
g_return_if_fail(font_name != NULL);
|
2008-07-11 17:09:01 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* do nothing if font has not changed */
|
2008-05-16 12:08:39 +00:00
|
|
|
if (interface_prefs.editor_font != NULL)
|
2009-04-05 21:07:40 +00:00
|
|
|
if (strcmp(font_name, interface_prefs.editor_font) == 0)
|
|
|
|
return;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-05-16 12:08:39 +00:00
|
|
|
g_free(interface_prefs.editor_font);
|
|
|
|
interface_prefs.editor_font = g_strdup(font_name);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
|
|
|
/* We copy the current style, and update the font in all open tabs. */
|
2008-07-11 17:09:01 +00:00
|
|
|
for (i = 0; i < documents_array->len; i++)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-07-11 14:11:53 +00:00
|
|
|
if (documents[i]->editor)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-07-11 17:09:01 +00:00
|
|
|
editor_set_font(documents[i]->editor, interface_prefs.editor_font);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-16 12:08:39 +00:00
|
|
|
ui_set_statusbar(TRUE, _("Font updated (%s)."), interface_prefs.editor_font);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
void ui_set_fullscreen(void)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2007-08-23 11:34:06 +00:00
|
|
|
if (ui_prefs.fullscreen)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-05-22 14:41:28 +00:00
|
|
|
gtk_window_fullscreen(GTK_WINDOW(main_widgets.window));
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-05-22 14:41:28 +00:00
|
|
|
gtk_window_unfullscreen(GTK_WINDOW(main_widgets.window));
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
void ui_update_popup_reundo_items(GeanyDocument *doc)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
gboolean enable_undo;
|
|
|
|
gboolean enable_redo;
|
2008-12-06 11:10:06 +00:00
|
|
|
guint i, len;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
if (doc == NULL)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
enable_undo = FALSE;
|
|
|
|
enable_redo = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-06-15 13:35:48 +00:00
|
|
|
enable_undo = document_can_undo(doc);
|
|
|
|
enable_redo = document_can_redo(doc);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* index 0 is the popup menu, 1 is the menubar, 2 is the toolbar */
|
2008-12-06 11:10:06 +00:00
|
|
|
len = G_N_ELEMENTS(widgets.undo_items);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
ui_widget_set_sensitive(widgets.undo_items[i], enable_undo);
|
|
|
|
}
|
|
|
|
len = G_N_ELEMENTS(widgets.redo_items);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
2009-05-28 20:22:12 +00:00
|
|
|
ui_widget_set_sensitive(widgets.redo_items[i], enable_redo);
|
2008-12-06 11:10:06 +00:00
|
|
|
}
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
void ui_update_popup_copy_items(GeanyDocument *doc)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
gboolean enable;
|
2008-12-06 11:10:06 +00:00
|
|
|
guint i, len;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
if (doc == NULL)
|
|
|
|
enable = FALSE;
|
|
|
|
else
|
2008-09-17 18:02:55 +00:00
|
|
|
enable = sci_has_selection(doc->editor->sci);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-12-06 11:10:06 +00:00
|
|
|
len = G_N_ELEMENTS(widgets.popup_copy_items);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
ui_widget_set_sensitive(widgets.popup_copy_items[i], enable);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ui_update_popup_goto_items(gboolean enable)
|
|
|
|
{
|
2008-12-06 11:10:06 +00:00
|
|
|
guint i, len;
|
|
|
|
len = G_N_ELEMENTS(widgets.popup_goto_items);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
ui_widget_set_sensitive(widgets.popup_goto_items[i], enable);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
void ui_update_menu_copy_items(GeanyDocument *doc)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
gboolean enable = FALSE;
|
2008-12-06 11:10:06 +00:00
|
|
|
guint i, len;
|
2008-05-22 14:41:28 +00:00
|
|
|
GtkWidget *focusw = gtk_window_get_focus(GTK_WINDOW(main_widgets.window));
|
2006-09-05 14:24:47 +00:00
|
|
|
|
|
|
|
if (IS_SCINTILLA(focusw))
|
2008-09-17 18:02:55 +00:00
|
|
|
enable = (doc == NULL) ? FALSE : sci_has_selection(doc->editor->sci);
|
2006-09-05 14:24:47 +00:00
|
|
|
else
|
|
|
|
if (GTK_IS_EDITABLE(focusw))
|
|
|
|
enable = gtk_editable_get_selection_bounds(GTK_EDITABLE(focusw), NULL, NULL);
|
|
|
|
else
|
|
|
|
if (GTK_IS_TEXT_VIEW(focusw))
|
|
|
|
{
|
|
|
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer(
|
|
|
|
GTK_TEXT_VIEW(focusw));
|
|
|
|
enable = gtk_text_buffer_get_selection_bounds(buffer, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2008-12-06 11:10:06 +00:00
|
|
|
len = G_N_ELEMENTS(widgets.menu_copy_items);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
ui_widget_set_sensitive(widgets.menu_copy_items[i], enable);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
void ui_update_insert_include_item(GeanyDocument *doc, gint item)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
gboolean enable = FALSE;
|
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
if (doc == NULL || doc->file_type == NULL)
|
2008-06-15 13:35:48 +00:00
|
|
|
enable = FALSE;
|
2009-04-15 22:47:33 +00:00
|
|
|
else if (doc->file_type->id == GEANY_FILETYPES_C || doc->file_type->id == GEANY_FILETYPES_CPP)
|
2006-09-05 14:24:47 +00:00
|
|
|
enable = TRUE;
|
2009-04-15 22:47:33 +00:00
|
|
|
|
2008-12-06 11:10:06 +00:00
|
|
|
ui_widget_set_sensitive(widgets.menu_insert_include_items[item], enable);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
void ui_update_fold_items(void)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-12-18 21:21:53 +00:00
|
|
|
ui_widget_show_hide(ui_lookup_widget(main_widgets.window, "menu_fold_all1"), editor_prefs.folding);
|
|
|
|
ui_widget_show_hide(ui_lookup_widget(main_widgets.window, "menu_unfold_all1"), editor_prefs.folding);
|
|
|
|
ui_widget_show_hide(ui_lookup_widget(main_widgets.window, "separator22"), editor_prefs.folding);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void insert_include_items(GtkMenu *me, GtkMenu *mp, gchar **includes, gchar *label)
|
|
|
|
{
|
|
|
|
guint i = 0;
|
|
|
|
GtkWidget *tmp_menu;
|
|
|
|
GtkWidget *tmp_popup;
|
|
|
|
GtkWidget *edit_menu, *edit_menu_item;
|
|
|
|
GtkWidget *popup_menu, *popup_menu_item;
|
|
|
|
|
|
|
|
edit_menu = gtk_menu_new();
|
|
|
|
popup_menu = gtk_menu_new();
|
|
|
|
edit_menu_item = gtk_menu_item_new_with_label(label);
|
|
|
|
popup_menu_item = gtk_menu_item_new_with_label(label);
|
|
|
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit_menu_item), edit_menu);
|
|
|
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(popup_menu_item), popup_menu);
|
|
|
|
|
|
|
|
while (includes[i] != NULL)
|
|
|
|
{
|
|
|
|
tmp_menu = gtk_menu_item_new_with_label(includes[i]);
|
|
|
|
tmp_popup = gtk_menu_item_new_with_label(includes[i]);
|
|
|
|
gtk_container_add(GTK_CONTAINER(edit_menu), tmp_menu);
|
|
|
|
gtk_container_add(GTK_CONTAINER(popup_menu), tmp_popup);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(tmp_menu, "activate",
|
2006-12-17 19:31:32 +00:00
|
|
|
G_CALLBACK(on_menu_insert_include_activate), (gpointer) includes[i]);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(tmp_popup, "activate",
|
2006-12-17 19:31:32 +00:00
|
|
|
G_CALLBACK(on_insert_include_activate), (gpointer) includes[i]);
|
2006-09-05 14:24:47 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
gtk_widget_show_all(edit_menu_item);
|
|
|
|
gtk_widget_show_all(popup_menu_item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(me), edit_menu_item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(mp), popup_menu_item);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
void ui_create_insert_menu_items(void)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-12-18 21:21:53 +00:00
|
|
|
GtkMenu *menu_edit = GTK_MENU(ui_lookup_widget(main_widgets.window, "insert_include2_menu"));
|
|
|
|
GtkMenu *menu_popup = GTK_MENU(ui_lookup_widget(main_widgets.editor_menu, "insert_include1_menu"));
|
2006-09-05 14:24:47 +00:00
|
|
|
GtkWidget *blank;
|
|
|
|
const gchar *c_includes_stdlib[] = {
|
|
|
|
"assert.h", "ctype.h", "errno.h", "float.h", "limits.h", "locale.h", "math.h", "setjmp.h",
|
|
|
|
"signal.h", "stdarg.h", "stddef.h", "stdio.h", "stdlib.h", "string.h", "time.h", NULL
|
|
|
|
};
|
|
|
|
const gchar *c_includes_c99[] = {
|
|
|
|
"complex.h", "fenv.h", "inttypes.h", "iso646.h", "stdbool.h", "stdint.h",
|
|
|
|
"tgmath.h", "wchar.h", "wctype.h", NULL
|
|
|
|
};
|
|
|
|
const gchar *c_includes_cpp[] = {
|
|
|
|
"cstdio", "cstring", "cctype", "cmath", "ctime", "cstdlib", "cstdarg", NULL
|
|
|
|
};
|
|
|
|
const gchar *c_includes_cppstdlib[] = {
|
|
|
|
"iostream", "fstream", "iomanip", "sstream", "exception", "stdexcept",
|
|
|
|
"memory", "locale", NULL
|
|
|
|
};
|
|
|
|
const gchar *c_includes_stl[] = {
|
|
|
|
"bitset", "dequev", "list", "map", "set", "queue", "stack", "vector", "algorithm",
|
|
|
|
"iterator", "functional", "string", "complex", "valarray", NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
blank = gtk_menu_item_new_with_label("#include \"...\"");
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu_edit), blank);
|
|
|
|
gtk_widget_show(blank);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(blank, "activate", G_CALLBACK(on_menu_insert_include_activate),
|
2006-09-05 14:24:47 +00:00
|
|
|
(gpointer) "blank");
|
|
|
|
blank = gtk_separator_menu_item_new ();
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu_edit), blank);
|
|
|
|
gtk_widget_show(blank);
|
|
|
|
|
|
|
|
blank = gtk_menu_item_new_with_label("#include \"...\"");
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu_popup), blank);
|
|
|
|
gtk_widget_show(blank);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(blank, "activate", G_CALLBACK(on_insert_include_activate),
|
2006-09-05 14:24:47 +00:00
|
|
|
(gpointer) "blank");
|
|
|
|
blank = gtk_separator_menu_item_new();
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu_popup), blank);
|
|
|
|
gtk_widget_show(blank);
|
|
|
|
|
|
|
|
insert_include_items(menu_edit, menu_popup, (gchar**) c_includes_stdlib, _("C Standard Library"));
|
|
|
|
insert_include_items(menu_edit, menu_popup, (gchar**) c_includes_c99, _("ISO C99"));
|
|
|
|
insert_include_items(menu_edit, menu_popup, (gchar**) c_includes_cpp, _("C++ (C Standard Library)"));
|
|
|
|
insert_include_items(menu_edit, menu_popup, (gchar**) c_includes_cppstdlib, _("C++ Standard Library"));
|
|
|
|
insert_include_items(menu_edit, menu_popup, (gchar**) c_includes_stl, _("C++ STL"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void insert_date_items(GtkMenu *me, GtkMenu *mp, gchar *label)
|
|
|
|
{
|
|
|
|
GtkWidget *item;
|
|
|
|
|
2007-10-13 09:35:34 +00:00
|
|
|
item = gtk_menu_item_new_with_mnemonic(label);
|
2006-09-05 14:24:47 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(me), item);
|
|
|
|
gtk_widget_show(item);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_menu_insert_date_activate), label);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2007-10-13 09:35:34 +00:00
|
|
|
item = gtk_menu_item_new_with_mnemonic(label);
|
2006-09-05 14:24:47 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(mp), item);
|
|
|
|
gtk_widget_show(item);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_insert_date_activate), label);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
void ui_create_insert_date_menu_items(void)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-12-18 21:21:53 +00:00
|
|
|
GtkMenu *menu_edit = GTK_MENU(ui_lookup_widget(main_widgets.window, "insert_date1_menu"));
|
|
|
|
GtkMenu *menu_popup = GTK_MENU(ui_lookup_widget(main_widgets.editor_menu, "insert_date2_menu"));
|
2006-09-05 14:24:47 +00:00
|
|
|
GtkWidget *item;
|
2006-12-12 12:12:20 +00:00
|
|
|
gchar *str;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
|
|
|
insert_date_items(menu_edit, menu_popup, _("dd.mm.yyyy"));
|
|
|
|
insert_date_items(menu_edit, menu_popup, _("mm.dd.yyyy"));
|
|
|
|
insert_date_items(menu_edit, menu_popup, _("yyyy/mm/dd"));
|
|
|
|
|
|
|
|
item = gtk_separator_menu_item_new();
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu_edit), item);
|
|
|
|
gtk_widget_show(item);
|
|
|
|
item = gtk_separator_menu_item_new();
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu_popup), item);
|
|
|
|
gtk_widget_show(item);
|
|
|
|
|
|
|
|
insert_date_items(menu_edit, menu_popup, _("dd.mm.yyyy hh:mm:ss"));
|
|
|
|
insert_date_items(menu_edit, menu_popup, _("mm.dd.yyyy hh:mm:ss"));
|
|
|
|
insert_date_items(menu_edit, menu_popup, _("yyyy/mm/dd hh:mm:ss"));
|
|
|
|
|
|
|
|
item = gtk_separator_menu_item_new();
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu_edit), item);
|
|
|
|
gtk_widget_show(item);
|
|
|
|
item = gtk_separator_menu_item_new();
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu_popup), item);
|
|
|
|
gtk_widget_show(item);
|
|
|
|
|
2007-10-13 09:35:34 +00:00
|
|
|
str = _("_Use Custom Date Format");
|
|
|
|
item = gtk_menu_item_new_with_mnemonic(str);
|
2006-09-05 14:24:47 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(menu_edit), item);
|
|
|
|
gtk_widget_show(item);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_menu_insert_date_activate), str);
|
2010-06-23 16:57:28 +00:00
|
|
|
ui_hookup_widget(main_widgets.window, item, "insert_date_custom1");
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2007-10-13 09:35:34 +00:00
|
|
|
item = gtk_menu_item_new_with_mnemonic(str);
|
2006-09-05 14:24:47 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(menu_popup), item);
|
|
|
|
gtk_widget_show(item);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_insert_date_activate), str);
|
2010-06-23 16:57:28 +00:00
|
|
|
ui_hookup_widget(main_widgets.editor_menu, item, "insert_date_custom2");
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2007-10-13 09:35:34 +00:00
|
|
|
insert_date_items(menu_edit, menu_popup, _("_Set Custom Date Format"));
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ui_save_buttons_toggle(gboolean enable)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
gboolean dirty_tabs = FALSE;
|
|
|
|
|
2009-01-28 17:01:32 +00:00
|
|
|
if (ui_prefs.allow_always_save)
|
|
|
|
return;
|
|
|
|
|
2008-12-06 11:10:06 +00:00
|
|
|
ui_widget_set_sensitive(widgets.save_buttons[0], enable);
|
|
|
|
ui_widget_set_sensitive(widgets.save_buttons[1], enable);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* save all menu item and tool button */
|
2008-05-29 17:00:54 +00:00
|
|
|
for (i = 0; i < documents_array->len; i++)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-03-23 16:43:01 +00:00
|
|
|
/* check whether there are files where changes were made and if there are some,
|
2008-02-27 13:17:29 +00:00
|
|
|
* we need the save all button / item */
|
2008-06-18 14:18:26 +00:00
|
|
|
if (documents[i]->is_valid && documents[i]->changed)
|
2008-03-23 16:43:01 +00:00
|
|
|
{
|
2006-09-05 14:24:47 +00:00
|
|
|
dirty_tabs = TRUE;
|
2008-03-23 16:43:01 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
2008-12-06 11:10:06 +00:00
|
|
|
ui_widget_set_sensitive(widgets.save_buttons[2], dirty_tabs);
|
|
|
|
ui_widget_set_sensitive(widgets.save_buttons[3], dirty_tabs);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-30 11:49:39 +00:00
|
|
|
#define add_doc_widget(widget_name) \
|
2008-12-18 21:21:53 +00:00
|
|
|
g_ptr_array_add(widgets.document_buttons, ui_lookup_widget(main_widgets.window, widget_name))
|
2008-06-30 11:49:39 +00:00
|
|
|
|
2008-12-06 11:10:06 +00:00
|
|
|
#define add_doc_toolitem(widget_name) \
|
2009-06-20 16:51:32 +00:00
|
|
|
g_ptr_array_add(widgets.document_buttons, toolbar_get_action_by_name(widget_name))
|
2008-12-06 11:10:06 +00:00
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
static void init_document_widgets(void)
|
2007-07-20 12:06:51 +00:00
|
|
|
{
|
2008-06-30 15:15:02 +00:00
|
|
|
widgets.document_buttons = g_ptr_array_new();
|
2008-06-30 11:49:39 +00:00
|
|
|
|
2007-07-20 12:06:51 +00:00
|
|
|
/* Cache the document-sensitive widgets so we don't have to keep looking them up
|
|
|
|
* when using ui_document_buttons_update(). */
|
2008-06-30 11:49:39 +00:00
|
|
|
add_doc_widget("menu_close1");
|
|
|
|
add_doc_widget("close_other_documents1");
|
|
|
|
add_doc_widget("menu_change_font1");
|
|
|
|
add_doc_widget("menu_close_all1");
|
2009-01-28 17:01:32 +00:00
|
|
|
add_doc_widget("menu_save1");
|
2008-06-30 11:49:39 +00:00
|
|
|
add_doc_widget("menu_save_all1");
|
|
|
|
add_doc_widget("menu_save_as1");
|
|
|
|
add_doc_widget("menu_count_words1");
|
|
|
|
add_doc_widget("menu_build1");
|
|
|
|
add_doc_widget("add_comments1");
|
|
|
|
add_doc_widget("menu_paste1");
|
|
|
|
add_doc_widget("menu_undo2");
|
|
|
|
add_doc_widget("preferences2");
|
|
|
|
add_doc_widget("menu_reload1");
|
|
|
|
add_doc_widget("menu_document1");
|
|
|
|
add_doc_widget("menu_choose_color1");
|
|
|
|
add_doc_widget("menu_zoom_in1");
|
|
|
|
add_doc_widget("menu_zoom_out1");
|
2008-12-07 19:12:08 +00:00
|
|
|
add_doc_widget("menu_view_editor1");
|
2008-06-30 11:49:39 +00:00
|
|
|
add_doc_widget("normal_size1");
|
|
|
|
add_doc_widget("treeview6");
|
|
|
|
add_doc_widget("print1");
|
|
|
|
add_doc_widget("menu_reload_as1");
|
|
|
|
add_doc_widget("menu_select_all1");
|
|
|
|
add_doc_widget("insert_date1");
|
|
|
|
add_doc_widget("menu_format1");
|
2009-10-28 11:06:31 +00:00
|
|
|
add_doc_widget("commands2");
|
2008-06-30 11:49:39 +00:00
|
|
|
add_doc_widget("menu_open_selected_file1");
|
|
|
|
add_doc_widget("page_setup1");
|
|
|
|
add_doc_widget("find1");
|
|
|
|
add_doc_widget("find_next1");
|
|
|
|
add_doc_widget("find_previous1");
|
|
|
|
add_doc_widget("replace1");
|
|
|
|
add_doc_widget("find_nextsel1");
|
|
|
|
add_doc_widget("find_prevsel1");
|
|
|
|
add_doc_widget("go_to_line1");
|
2008-12-06 11:10:06 +00:00
|
|
|
add_doc_toolitem("Close");
|
2008-12-09 20:31:38 +00:00
|
|
|
add_doc_toolitem("CloseAll");
|
2008-12-06 11:10:06 +00:00
|
|
|
add_doc_toolitem("Search");
|
|
|
|
add_doc_toolitem("SearchEntry");
|
|
|
|
add_doc_toolitem("NavBack");
|
|
|
|
add_doc_toolitem("NavFor");
|
|
|
|
add_doc_toolitem("ZoomIn");
|
|
|
|
add_doc_toolitem("ZoomOut");
|
|
|
|
add_doc_toolitem("Indent");
|
|
|
|
add_doc_toolitem("UnIndent");
|
|
|
|
add_doc_toolitem("Cut");
|
|
|
|
add_doc_toolitem("Copy");
|
|
|
|
add_doc_toolitem("Paste");
|
|
|
|
add_doc_toolitem("Delete");
|
2009-01-28 17:01:32 +00:00
|
|
|
add_doc_toolitem("Save");
|
2008-12-06 11:10:06 +00:00
|
|
|
add_doc_toolitem("SaveAll");
|
|
|
|
add_doc_toolitem("Compile");
|
|
|
|
add_doc_toolitem("Run");
|
|
|
|
add_doc_toolitem("Reload");
|
|
|
|
add_doc_toolitem("Color");
|
|
|
|
add_doc_toolitem("Goto");
|
|
|
|
add_doc_toolitem("GotoEntry");
|
2010-05-22 19:39:14 +00:00
|
|
|
add_doc_toolitem("Replace");
|
|
|
|
add_doc_toolitem("Print");
|
2007-07-20 12:06:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
void ui_document_buttons_update(void)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
guint i;
|
2008-05-22 14:41:28 +00:00
|
|
|
gboolean enable = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)) ? TRUE : FALSE;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-06-30 11:49:39 +00:00
|
|
|
for (i = 0; i < widgets.document_buttons->len; i++)
|
|
|
|
{
|
|
|
|
GtkWidget *widget = g_ptr_array_index(widgets.document_buttons, i);
|
2009-06-20 16:51:32 +00:00
|
|
|
if (GTK_IS_ACTION(widget))
|
|
|
|
gtk_action_set_sensitive(GTK_ACTION(widget), enable);
|
|
|
|
else
|
|
|
|
ui_widget_set_sensitive(widget, enable);
|
2008-06-30 11:49:39 +00:00
|
|
|
}
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-14 14:49:41 +00:00
|
|
|
static void on_doc_sensitive_widget_destroy(GtkWidget *widget, G_GNUC_UNUSED gpointer user_data)
|
|
|
|
{
|
|
|
|
g_ptr_array_remove_fast(widgets.document_buttons, widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-12 18:15:48 +00:00
|
|
|
/** Adds a widget to the list of widgets that should be set sensitive/insensitive
|
2008-10-14 14:49:41 +00:00
|
|
|
* when some documents are present/no documents are open.
|
|
|
|
* It will be removed when the widget is destroyed.
|
2009-01-30 18:53:23 +00:00
|
|
|
* @param widget The widget to add.
|
|
|
|
*
|
|
|
|
* @since 0.15
|
|
|
|
**/
|
2008-10-14 14:49:41 +00:00
|
|
|
void ui_add_document_sensitive(GtkWidget *widget)
|
|
|
|
{
|
2008-10-15 12:19:24 +00:00
|
|
|
gboolean enable = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)) ? TRUE : FALSE;
|
|
|
|
|
2008-12-06 11:10:06 +00:00
|
|
|
ui_widget_set_sensitive(widget, enable);
|
2008-10-15 12:19:24 +00:00
|
|
|
|
2008-10-14 14:49:41 +00:00
|
|
|
g_ptr_array_add(widgets.document_buttons, widget);
|
|
|
|
g_signal_connect(widget, "destroy", G_CALLBACK(on_doc_sensitive_widget_destroy), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-09-05 14:24:47 +00:00
|
|
|
void ui_widget_show_hide(GtkWidget *widget, gboolean show)
|
|
|
|
{
|
|
|
|
if (show)
|
|
|
|
{
|
|
|
|
gtk_widget_show(widget);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_widget_hide(widget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
void ui_sidebar_show_hide(void)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
GtkWidget *widget;
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* check that there are no other notebook pages before hiding the sidebar completely
|
|
|
|
* other pages could be e.g. the file browser plugin */
|
2008-05-16 12:08:39 +00:00
|
|
|
if (! interface_prefs.sidebar_openfiles_visible && ! interface_prefs.sidebar_symbol_visible &&
|
2008-05-22 14:41:28 +00:00
|
|
|
gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.sidebar_notebook)) <= 2)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2007-08-23 11:34:06 +00:00
|
|
|
ui_prefs.sidebar_visible = FALSE;
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
2008-12-18 21:21:53 +00:00
|
|
|
widget = ui_lookup_widget(main_widgets.window, "menu_show_sidebar1");
|
2007-08-23 11:34:06 +00:00
|
|
|
if (ui_prefs.sidebar_visible != gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-05-22 14:41:28 +00:00
|
|
|
ignore_callback = TRUE;
|
2007-08-23 11:34:06 +00:00
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), ui_prefs.sidebar_visible);
|
2008-05-22 14:41:28 +00:00
|
|
|
ignore_callback = FALSE;
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
2008-05-22 14:41:28 +00:00
|
|
|
ui_widget_show_hide(main_widgets.sidebar_notebook, ui_prefs.sidebar_visible);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
|
|
|
ui_widget_show_hide(gtk_notebook_get_nth_page(
|
2009-04-27 19:30:29 +00:00
|
|
|
GTK_NOTEBOOK(main_widgets.sidebar_notebook), 0), interface_prefs.sidebar_symbol_visible);
|
2006-09-05 14:24:47 +00:00
|
|
|
ui_widget_show_hide(gtk_notebook_get_nth_page(
|
2009-04-27 19:30:29 +00:00
|
|
|
GTK_NOTEBOOK(main_widgets.sidebar_notebook), 1), interface_prefs.sidebar_openfiles_visible);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
void ui_document_show_hide(GeanyDocument *doc)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2010-04-25 17:43:39 +00:00
|
|
|
const gchar *widget_name;
|
2007-10-17 12:27:07 +00:00
|
|
|
GtkWidget *item;
|
2008-08-04 14:07:49 +00:00
|
|
|
const GeanyIndentPrefs *iprefs;
|
2007-03-08 18:02:08 +00:00
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
if (doc == NULL)
|
|
|
|
doc = document_get_current();
|
2007-03-08 18:02:08 +00:00
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
if (doc == NULL)
|
2007-03-08 18:02:08 +00:00
|
|
|
return;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-05-22 14:41:28 +00:00
|
|
|
ignore_callback = TRUE;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
|
|
|
gtk_check_menu_item_set_active(
|
2008-12-18 21:21:53 +00:00
|
|
|
GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "menu_line_wrapping1")),
|
2008-07-08 16:30:37 +00:00
|
|
|
doc->editor->line_wrapping);
|
2007-10-17 12:27:07 +00:00
|
|
|
|
2008-05-09 12:13:29 +00:00
|
|
|
gtk_check_menu_item_set_active(
|
2008-12-18 21:21:53 +00:00
|
|
|
GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "line_breaking1")),
|
2008-07-08 16:30:37 +00:00
|
|
|
doc->editor->line_breaking);
|
2008-05-09 12:13:29 +00:00
|
|
|
|
2008-08-04 14:07:49 +00:00
|
|
|
iprefs = editor_get_indent_prefs(doc->editor);
|
|
|
|
|
2008-12-18 21:21:53 +00:00
|
|
|
item = ui_lookup_widget(main_widgets.window, "menu_use_auto_indentation1");
|
2008-07-08 16:30:37 +00:00
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), doc->editor->auto_indent);
|
2007-10-17 12:27:07 +00:00
|
|
|
|
2008-08-04 14:07:49 +00:00
|
|
|
switch (iprefs->type)
|
|
|
|
{
|
|
|
|
case GEANY_INDENT_TYPE_SPACES:
|
|
|
|
widget_name = "spaces1"; break;
|
|
|
|
case GEANY_INDENT_TYPE_TABS:
|
|
|
|
widget_name = "tabs1"; break;
|
|
|
|
case GEANY_INDENT_TYPE_BOTH:
|
2008-08-17 14:20:30 +00:00
|
|
|
default:
|
2008-08-04 14:07:49 +00:00
|
|
|
widget_name = "tabs_and_spaces1"; break;
|
|
|
|
}
|
2008-12-18 21:21:53 +00:00
|
|
|
item = ui_lookup_widget(main_widgets.window, widget_name);
|
2007-10-17 12:27:07 +00:00
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
|
|
|
|
|
2006-09-05 14:24:47 +00:00
|
|
|
gtk_check_menu_item_set_active(
|
2008-12-18 21:21:53 +00:00
|
|
|
GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "set_file_readonly1")),
|
2008-06-15 13:35:48 +00:00
|
|
|
doc->readonly);
|
2007-10-17 12:27:07 +00:00
|
|
|
|
2008-12-18 21:21:53 +00:00
|
|
|
item = ui_lookup_widget(main_widgets.window, "menu_write_unicode_bom1");
|
2008-06-15 13:35:48 +00:00
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), doc->has_bom);
|
2008-12-06 11:10:06 +00:00
|
|
|
ui_widget_set_sensitive(item, encodings_is_unicode_charset(doc->encoding));
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-07-14 11:13:54 +00:00
|
|
|
switch (sci_get_eol_mode(doc->editor->sci))
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
case SC_EOL_CR: widget_name = "cr"; break;
|
|
|
|
case SC_EOL_LF: widget_name = "lf"; break;
|
|
|
|
default: widget_name = "crlf"; break;
|
|
|
|
}
|
2007-10-17 12:27:07 +00:00
|
|
|
gtk_check_menu_item_set_active(
|
2008-12-18 21:21:53 +00:00
|
|
|
GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, widget_name)), TRUE);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
encodings_select_radio_item(doc->encoding);
|
|
|
|
filetypes_select_radio_item(doc->file_type);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-05-22 14:41:28 +00:00
|
|
|
ignore_callback = FALSE;
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-27 14:05:50 +00:00
|
|
|
void ui_set_search_entry_background(GtkWidget *widget, gboolean success)
|
|
|
|
{
|
|
|
|
static const GdkColor red = {0, 0xffff, 0x6666, 0x6666};
|
|
|
|
static const GdkColor white = {0, 0xffff, 0xffff, 0xffff};
|
|
|
|
static gboolean old_value = TRUE;
|
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
g_return_if_fail(widget != NULL);
|
2009-02-27 14:05:50 +00:00
|
|
|
|
|
|
|
/* update only if really needed */
|
|
|
|
if (old_value != success)
|
|
|
|
{
|
|
|
|
gtk_widget_modify_base(widget, GTK_STATE_NORMAL, success ? NULL : &red);
|
|
|
|
gtk_widget_modify_text(widget, GTK_STATE_NORMAL, success ? NULL : &white);
|
|
|
|
|
|
|
|
old_value = success;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-20 17:32:55 +00:00
|
|
|
static gboolean have_tango_icon_theme(void)
|
2009-06-05 14:00:08 +00:00
|
|
|
{
|
|
|
|
static gboolean result = FALSE;
|
|
|
|
static gboolean checked = FALSE;
|
|
|
|
|
|
|
|
if (! checked)
|
|
|
|
{
|
|
|
|
gchar *theme_name;
|
|
|
|
|
|
|
|
g_object_get(G_OBJECT(gtk_settings_get_default()), "gtk-icon-theme-name", &theme_name, NULL);
|
|
|
|
setptr(theme_name, g_utf8_strdown(theme_name, -1));
|
|
|
|
|
2009-06-20 17:32:55 +00:00
|
|
|
result = (strstr(theme_name, "tango") != NULL);
|
2009-06-05 14:00:08 +00:00
|
|
|
checked = TRUE;
|
|
|
|
|
|
|
|
g_free(theme_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* Note: remember to unref the pixbuf once an image or window has added a reference. */
|
2008-12-09 20:31:38 +00:00
|
|
|
GdkPixbuf *ui_new_pixbuf_from_inline(gint img)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2009-09-16 14:13:38 +00:00
|
|
|
switch (img)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-12-06 11:45:48 +00:00
|
|
|
case GEANY_IMAGE_LOGO:
|
|
|
|
return gdk_pixbuf_new_from_inline(-1, aladin_inline, FALSE, NULL);
|
|
|
|
break;
|
2006-09-05 14:24:47 +00:00
|
|
|
case GEANY_IMAGE_SAVE_ALL:
|
|
|
|
{
|
2009-06-05 14:00:08 +00:00
|
|
|
/* check whether the icon theme looks like a Gnome icon theme, if so use the
|
|
|
|
* old Gnome based Save All icon, otherwise assume a Tango-like icon theme */
|
2009-06-20 17:32:55 +00:00
|
|
|
if (have_tango_icon_theme())
|
2009-06-05 14:00:08 +00:00
|
|
|
return gdk_pixbuf_new_from_inline(-1, save_all_tango_inline, FALSE, NULL);
|
2009-06-20 17:32:55 +00:00
|
|
|
else
|
|
|
|
return gdk_pixbuf_new_from_inline(-1, save_all_gnome_inline, FALSE, NULL);
|
2006-09-05 14:24:47 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-12-09 20:31:38 +00:00
|
|
|
case GEANY_IMAGE_CLOSE_ALL:
|
|
|
|
{
|
|
|
|
return gdk_pixbuf_new_from_inline(-1, close_all_inline, FALSE, NULL);
|
|
|
|
break;
|
|
|
|
}
|
2009-01-17 17:59:20 +00:00
|
|
|
case GEANY_IMAGE_BUILD:
|
|
|
|
{
|
|
|
|
return gdk_pixbuf_new_from_inline(-1, build_inline, FALSE, NULL);
|
|
|
|
break;
|
|
|
|
}
|
2008-12-06 11:45:48 +00:00
|
|
|
default:
|
|
|
|
return NULL;
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-09 20:31:38 +00:00
|
|
|
static GdkPixbuf *ui_new_pixbuf_from_stock(const gchar *stock_id)
|
|
|
|
{
|
|
|
|
if (utils_str_equal(stock_id, GEANY_STOCK_CLOSE_ALL))
|
|
|
|
return ui_new_pixbuf_from_inline(GEANY_IMAGE_CLOSE_ALL);
|
2009-01-17 17:59:20 +00:00
|
|
|
else if (utils_str_equal(stock_id, GEANY_STOCK_BUILD))
|
|
|
|
return ui_new_pixbuf_from_inline(GEANY_IMAGE_BUILD);
|
2008-12-09 20:31:38 +00:00
|
|
|
else if (utils_str_equal(stock_id, GEANY_STOCK_SAVE_ALL))
|
|
|
|
return ui_new_pixbuf_from_inline(GEANY_IMAGE_SAVE_ALL);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GtkWidget *ui_new_image_from_inline(gint img)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2006-12-13 15:18:49 +00:00
|
|
|
GtkWidget *wid;
|
|
|
|
GdkPixbuf *pb;
|
|
|
|
|
2008-12-09 20:31:38 +00:00
|
|
|
pb = ui_new_pixbuf_from_inline(img);
|
2006-12-13 15:18:49 +00:00
|
|
|
wid = gtk_image_new_from_pixbuf(pb);
|
2008-02-27 13:17:29 +00:00
|
|
|
g_object_unref(pb); /* the image doesn't adopt our reference, so remove our ref. */
|
2006-12-13 15:18:49 +00:00
|
|
|
return wid;
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
static void recent_create_menu(GeanyRecentFiles *grf)
|
2006-09-09 14:36:15 +00:00
|
|
|
{
|
|
|
|
GtkWidget *tmp;
|
2008-12-06 16:57:52 +00:00
|
|
|
guint i, len;
|
2006-09-09 14:36:15 +00:00
|
|
|
gchar *filename;
|
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
len = MIN(file_prefs.mru_length, g_queue_get_length(grf->recent_queue));
|
2008-12-06 16:57:52 +00:00
|
|
|
for (i = 0; i < len; i++)
|
2006-09-09 14:36:15 +00:00
|
|
|
{
|
2009-04-05 14:14:29 +00:00
|
|
|
filename = g_queue_peek_nth(grf->recent_queue, i);
|
2008-02-27 13:17:29 +00:00
|
|
|
/* create menu item for the recent files menu in the menu bar */
|
2006-09-09 14:36:15 +00:00
|
|
|
tmp = gtk_menu_item_new_with_label(filename);
|
|
|
|
gtk_widget_show(tmp);
|
2009-04-05 14:14:29 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(grf->menubar), tmp);
|
|
|
|
g_signal_connect(tmp, "activate", G_CALLBACK(grf->activate_cb), NULL);
|
2008-12-06 11:10:06 +00:00
|
|
|
/* create menu item for the recent files menu in the toolbar */
|
2009-04-05 14:14:29 +00:00
|
|
|
if (grf->toolbar != NULL)
|
2008-12-06 11:10:06 +00:00
|
|
|
{
|
|
|
|
tmp = gtk_menu_item_new_with_label(filename);
|
|
|
|
gtk_widget_show(tmp);
|
2009-04-05 14:14:29 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(grf->toolbar), tmp);
|
|
|
|
g_signal_connect(tmp, "activate", G_CALLBACK(grf->activate_cb), NULL);
|
2008-12-06 11:10:06 +00:00
|
|
|
}
|
2006-09-09 14:36:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
static GeanyRecentFiles *recent_get_recent_files(void)
|
|
|
|
{
|
2009-04-07 22:09:23 +00:00
|
|
|
static GeanyRecentFiles grf = { RECENT_FILE_FILE, NULL, NULL, NULL, NULL };
|
2009-04-05 14:14:29 +00:00
|
|
|
|
2009-04-05 21:07:40 +00:00
|
|
|
if (G_UNLIKELY(grf.recent_queue == NULL))
|
2009-04-05 14:14:29 +00:00
|
|
|
{
|
|
|
|
grf.recent_queue = ui_prefs.recent_queue;
|
|
|
|
grf.menubar = ui_widgets.recent_files_menu_menubar;
|
2009-06-20 16:51:32 +00:00
|
|
|
grf.toolbar = geany_menu_button_action_get_menu(GEANY_MENU_BUTTON_ACTION(
|
|
|
|
toolbar_get_action_by_name("Open")));
|
2009-04-05 14:14:29 +00:00
|
|
|
grf.activate_cb = recent_file_activate_cb;
|
|
|
|
}
|
|
|
|
return &grf;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static GeanyRecentFiles *recent_get_recent_projects(void)
|
|
|
|
{
|
2009-04-07 22:09:23 +00:00
|
|
|
static GeanyRecentFiles grf = { RECENT_FILE_PROJECT, NULL, NULL, NULL, NULL };
|
2009-04-05 14:14:29 +00:00
|
|
|
|
2009-04-05 21:07:40 +00:00
|
|
|
if (G_UNLIKELY(grf.recent_queue == NULL))
|
2009-04-05 14:14:29 +00:00
|
|
|
{
|
|
|
|
grf.recent_queue = ui_prefs.recent_projects_queue;
|
|
|
|
grf.menubar = ui_widgets.recent_projects_menu_menubar;
|
|
|
|
grf.toolbar = NULL;
|
|
|
|
grf.activate_cb = recent_project_activate_cb;
|
|
|
|
}
|
|
|
|
return &grf;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ui_create_recent_menus(void)
|
|
|
|
{
|
|
|
|
recent_create_menu(recent_get_recent_files());
|
|
|
|
recent_create_menu(recent_get_recent_projects());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-06 16:57:52 +00:00
|
|
|
static void recent_file_activate_cb(GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data)
|
2006-09-09 14:36:15 +00:00
|
|
|
{
|
2008-05-13 17:18:14 +00:00
|
|
|
gchar *utf8_filename = ui_menu_item_get_text(menuitem);
|
2006-09-21 09:55:50 +00:00
|
|
|
gchar *locale_filename = utils_get_locale_from_utf8(utf8_filename);
|
2006-09-09 14:36:15 +00:00
|
|
|
|
2008-06-15 13:35:48 +00:00
|
|
|
if (document_open_file(locale_filename, FALSE, NULL, NULL) != NULL)
|
2009-04-05 14:14:29 +00:00
|
|
|
recent_file_loaded(utf8_filename, recent_get_recent_files());
|
2006-09-09 14:36:15 +00:00
|
|
|
|
|
|
|
g_free(locale_filename);
|
2006-09-21 09:55:50 +00:00
|
|
|
g_free(utf8_filename);
|
2006-09-09 14:36:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
static void recent_project_activate_cb(GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2009-04-05 14:14:29 +00:00
|
|
|
gchar *utf8_filename = ui_menu_item_get_text(menuitem);
|
|
|
|
gchar *locale_filename = utils_get_locale_from_utf8(utf8_filename);
|
|
|
|
|
|
|
|
if (project_ask_close() && project_load_file_with_session(locale_filename))
|
|
|
|
recent_file_loaded(utf8_filename, recent_get_recent_projects());
|
|
|
|
|
|
|
|
g_free(locale_filename);
|
|
|
|
g_free(utf8_filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void add_recent_file(const gchar *utf8_filename, GeanyRecentFiles *grf)
|
|
|
|
{
|
|
|
|
if (g_queue_find_custom(grf->recent_queue, utf8_filename, (GCompareFunc) strcmp) == NULL)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2007-10-13 10:41:38 +00:00
|
|
|
#if GTK_CHECK_VERSION(2, 10, 0)
|
2009-04-07 22:09:23 +00:00
|
|
|
if (grf->type == RECENT_FILE_FILE)
|
2007-10-13 10:41:38 +00:00
|
|
|
{
|
2009-04-07 22:09:23 +00:00
|
|
|
GtkRecentManager *manager = gtk_recent_manager_get_default();
|
|
|
|
gchar *uri = g_filename_to_uri(utf8_filename, NULL, NULL);
|
2009-04-15 22:47:33 +00:00
|
|
|
if (uri != NULL)
|
2009-04-07 22:09:23 +00:00
|
|
|
{
|
|
|
|
gtk_recent_manager_add_item(manager, uri);
|
|
|
|
g_free(uri);
|
|
|
|
}
|
2007-10-13 10:41:38 +00:00
|
|
|
}
|
|
|
|
#endif
|
2009-04-05 14:14:29 +00:00
|
|
|
g_queue_push_head(grf->recent_queue, g_strdup(utf8_filename));
|
|
|
|
if (g_queue_get_length(grf->recent_queue) > file_prefs.mru_length)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2009-04-05 14:14:29 +00:00
|
|
|
g_free(g_queue_pop_tail(grf->recent_queue));
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
2009-04-05 14:14:29 +00:00
|
|
|
update_recent_menu(grf);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
2009-04-05 14:14:29 +00:00
|
|
|
/* filename already in recent list */
|
|
|
|
else
|
|
|
|
recent_file_loaded(utf8_filename, grf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ui_add_recent_file(const gchar *utf8_filename)
|
|
|
|
{
|
|
|
|
add_recent_file(utf8_filename, recent_get_recent_files());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ui_add_recent_project_file(const gchar *utf8_filename)
|
|
|
|
{
|
|
|
|
add_recent_file(utf8_filename, recent_get_recent_projects());
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* Returns: newly allocated string with the UTF-8 menu text. */
|
2008-05-13 17:18:14 +00:00
|
|
|
gchar *ui_menu_item_get_text(GtkMenuItem *menu_item)
|
2006-09-17 21:53:47 +00:00
|
|
|
{
|
|
|
|
const gchar *text = NULL;
|
|
|
|
|
2006-12-01 18:44:35 +00:00
|
|
|
if (GTK_BIN(menu_item)->child)
|
2006-09-17 21:53:47 +00:00
|
|
|
{
|
2006-12-01 18:44:35 +00:00
|
|
|
GtkWidget *child = GTK_BIN(menu_item)->child;
|
2006-09-17 21:53:47 +00:00
|
|
|
|
2006-12-01 18:44:35 +00:00
|
|
|
if (GTK_IS_LABEL(child))
|
2006-09-17 21:53:47 +00:00
|
|
|
text = gtk_label_get_text(GTK_LABEL(child));
|
|
|
|
}
|
2008-02-27 13:17:29 +00:00
|
|
|
/* GTK owns text so it's much safer to return a copy of it in case the memory is reallocated */
|
2006-09-21 09:55:50 +00:00
|
|
|
return g_strdup(text);
|
2006-09-17 21:53:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-01 18:44:35 +00:00
|
|
|
static gint find_recent_file_item(gconstpointer list_data, gconstpointer user_data)
|
|
|
|
{
|
2008-05-13 17:18:14 +00:00
|
|
|
gchar *menu_text = ui_menu_item_get_text(GTK_MENU_ITEM(list_data));
|
2006-12-01 18:44:35 +00:00
|
|
|
gint result;
|
|
|
|
|
2006-12-07 16:09:45 +00:00
|
|
|
if (utils_str_equal(menu_text, user_data))
|
2006-12-01 18:44:35 +00:00
|
|
|
result = 0;
|
|
|
|
else
|
|
|
|
result = 1;
|
|
|
|
|
|
|
|
g_free(menu_text);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
static void recent_file_loaded(const gchar *utf8_filename, GeanyRecentFiles *grf)
|
2006-09-09 14:36:15 +00:00
|
|
|
{
|
2006-09-17 21:53:47 +00:00
|
|
|
GList *item, *children;
|
|
|
|
void *data;
|
2006-12-01 18:44:35 +00:00
|
|
|
GtkWidget *tmp;
|
2006-09-09 14:36:15 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* first reorder the queue */
|
2009-04-05 14:14:29 +00:00
|
|
|
item = g_queue_find_custom(grf->recent_queue, utf8_filename, (GCompareFunc) strcmp);
|
2006-09-17 21:53:47 +00:00
|
|
|
g_return_if_fail(item != NULL);
|
|
|
|
|
2006-09-09 14:36:15 +00:00
|
|
|
data = item->data;
|
2009-04-05 14:14:29 +00:00
|
|
|
g_queue_remove(grf->recent_queue, data);
|
|
|
|
g_queue_push_head(grf->recent_queue, data);
|
2006-09-09 14:36:15 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* remove the old menuitem for the filename */
|
2009-04-05 14:14:29 +00:00
|
|
|
children = gtk_container_get_children(GTK_CONTAINER(grf->menubar));
|
2006-12-01 18:44:35 +00:00
|
|
|
item = g_list_find_custom(children, utf8_filename, (GCompareFunc) find_recent_file_item);
|
2008-12-06 11:10:06 +00:00
|
|
|
if (item != NULL)
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(item->data));
|
2009-10-12 16:31:38 +00:00
|
|
|
g_list_free(children);
|
2006-09-17 21:53:47 +00:00
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
if (grf->toolbar != NULL)
|
2008-12-06 11:10:06 +00:00
|
|
|
{
|
2009-04-05 14:14:29 +00:00
|
|
|
children = gtk_container_get_children(GTK_CONTAINER(grf->toolbar));
|
2008-12-06 11:10:06 +00:00
|
|
|
item = g_list_find_custom(children, utf8_filename, (GCompareFunc) find_recent_file_item);
|
|
|
|
if (item != NULL)
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(item->data));
|
2009-10-12 16:31:38 +00:00
|
|
|
g_list_free(children);
|
2008-12-06 11:10:06 +00:00
|
|
|
}
|
2008-02-27 13:17:29 +00:00
|
|
|
/* now prepend a new menuitem for the filename,
|
|
|
|
* first for the recent files menu in the menu bar */
|
2006-09-17 21:53:47 +00:00
|
|
|
tmp = gtk_menu_item_new_with_label(utf8_filename);
|
|
|
|
gtk_widget_show(tmp);
|
2009-04-05 14:14:29 +00:00
|
|
|
gtk_menu_shell_prepend(GTK_MENU_SHELL(grf->menubar), tmp);
|
|
|
|
g_signal_connect(tmp, "activate", G_CALLBACK(grf->activate_cb), NULL);
|
2008-02-27 13:17:29 +00:00
|
|
|
/* then for the recent files menu in the tool bar */
|
2009-04-05 14:14:29 +00:00
|
|
|
if (grf->toolbar != NULL)
|
2008-12-06 11:10:06 +00:00
|
|
|
{
|
|
|
|
tmp = gtk_menu_item_new_with_label(utf8_filename);
|
|
|
|
gtk_widget_show(tmp);
|
2009-04-05 14:14:29 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(grf->toolbar), tmp);
|
2008-12-06 16:57:52 +00:00
|
|
|
/* this is a bit ugly, but we need to use gtk_container_add(). Using
|
|
|
|
* gtk_menu_shell_prepend() doesn't emit GtkContainer's "add" signal which we need in
|
|
|
|
* GeanyMenubuttonAction */
|
2009-04-05 14:14:29 +00:00
|
|
|
gtk_menu_reorder_child(GTK_MENU(grf->toolbar), tmp, 0);
|
|
|
|
g_signal_connect(tmp, "activate", G_CALLBACK(grf->activate_cb), NULL);
|
2008-12-06 11:10:06 +00:00
|
|
|
}
|
2006-09-09 14:36:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
static void update_recent_menu(GeanyRecentFiles *grf)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
|
|
|
GtkWidget *tmp;
|
|
|
|
gchar *filename;
|
2006-12-01 18:44:35 +00:00
|
|
|
GList *children, *item;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2009-04-05 14:14:29 +00:00
|
|
|
filename = g_queue_peek_head(grf->recent_queue);
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* clean the MRU list before adding an item (menubar) */
|
2009-04-05 14:14:29 +00:00
|
|
|
children = gtk_container_get_children(GTK_CONTAINER(grf->menubar));
|
2008-05-16 12:08:39 +00:00
|
|
|
if (g_list_length(children) > file_prefs.mru_length - 1)
|
2006-12-01 18:44:35 +00:00
|
|
|
{
|
2008-05-16 12:08:39 +00:00
|
|
|
item = g_list_nth(children, file_prefs.mru_length - 1);
|
2006-12-01 18:44:35 +00:00
|
|
|
while (item != NULL)
|
|
|
|
{
|
2008-12-06 11:10:06 +00:00
|
|
|
if (GTK_IS_MENU_ITEM(item->data))
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(item->data));
|
2006-12-01 18:44:35 +00:00
|
|
|
item = g_list_next(item);
|
|
|
|
}
|
|
|
|
}
|
2009-10-12 16:31:38 +00:00
|
|
|
g_list_free(children);
|
|
|
|
|
2008-12-06 11:10:06 +00:00
|
|
|
/* create item for the menu bar menu */
|
|
|
|
tmp = gtk_menu_item_new_with_label(filename);
|
|
|
|
gtk_widget_show(tmp);
|
2009-04-05 14:14:29 +00:00
|
|
|
gtk_menu_shell_prepend(GTK_MENU_SHELL(grf->menubar), tmp);
|
|
|
|
g_signal_connect(tmp, "activate", G_CALLBACK(grf->activate_cb), NULL);
|
2006-12-01 18:44:35 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* clean the MRU list before adding an item (toolbar) */
|
2009-04-05 14:14:29 +00:00
|
|
|
if (grf->toolbar != NULL)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2009-04-05 14:14:29 +00:00
|
|
|
children = gtk_container_get_children(GTK_CONTAINER(grf->toolbar));
|
2008-12-06 11:10:06 +00:00
|
|
|
if (g_list_length(children) > file_prefs.mru_length - 1)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-12-06 11:10:06 +00:00
|
|
|
item = g_list_nth(children, file_prefs.mru_length - 1);
|
|
|
|
while (item != NULL)
|
|
|
|
{
|
|
|
|
if (GTK_IS_MENU_ITEM(item->data))
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(item->data));
|
|
|
|
item = g_list_next(item);
|
|
|
|
}
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
2009-10-12 16:31:38 +00:00
|
|
|
g_list_free(children);
|
|
|
|
|
2008-12-06 11:10:06 +00:00
|
|
|
/* create item for the tool bar menu */
|
|
|
|
tmp = gtk_menu_item_new_with_label(filename);
|
|
|
|
gtk_widget_show(tmp);
|
2009-04-05 14:14:29 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(grf->toolbar), tmp);
|
|
|
|
gtk_menu_reorder_child(GTK_MENU(grf->toolbar), tmp, 0);
|
|
|
|
g_signal_connect(tmp, "activate", G_CALLBACK(grf->activate_cb), NULL);
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-07 19:12:08 +00:00
|
|
|
void ui_toggle_editor_features(GeanyUIEditorFeatures feature)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-06-15 13:35:48 +00:00
|
|
|
gint i, max = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook));
|
|
|
|
GeanyDocument *doc;
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2009-09-16 14:13:38 +00:00
|
|
|
for (i = 0; i < max; i++)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-06-15 13:35:48 +00:00
|
|
|
doc = document_get_from_page(i);
|
2008-12-07 19:12:08 +00:00
|
|
|
|
|
|
|
switch (feature)
|
|
|
|
{
|
|
|
|
case GEANY_EDITOR_SHOW_MARKERS_MARGIN:
|
|
|
|
sci_set_symbol_margin(doc->editor->sci, editor_prefs.show_markers_margin);
|
|
|
|
break;
|
|
|
|
case GEANY_EDITOR_SHOW_LINE_NUMBERS:
|
|
|
|
sci_set_line_numbers(doc->editor->sci, editor_prefs.show_linenumber_margin, 0);
|
|
|
|
break;
|
|
|
|
case GEANY_EDITOR_SHOW_WHITE_SPACE:
|
|
|
|
sci_set_visible_white_spaces(doc->editor->sci, editor_prefs.show_white_space);
|
|
|
|
break;
|
|
|
|
case GEANY_EDITOR_SHOW_LINE_ENDINGS:
|
|
|
|
sci_set_visible_eols(doc->editor->sci, editor_prefs.show_line_endings);
|
|
|
|
break;
|
|
|
|
case GEANY_EDITOR_SHOW_INDENTATION_GUIDES:
|
|
|
|
editor_set_indentation_guides(doc->editor);
|
|
|
|
break;
|
|
|
|
}
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-07 19:12:08 +00:00
|
|
|
void ui_update_view_editor_menu_items(void)
|
2006-09-05 14:24:47 +00:00
|
|
|
{
|
2008-12-07 19:12:08 +00:00
|
|
|
ignore_callback = TRUE;
|
2008-12-18 21:21:53 +00:00
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "menu_markers_margin1")), editor_prefs.show_markers_margin);
|
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "menu_linenumber_margin1")), editor_prefs.show_linenumber_margin);
|
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "menu_show_white_space1")), editor_prefs.show_white_space);
|
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "menu_show_line_endings1")), editor_prefs.show_line_endings);
|
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ui_lookup_widget(main_widgets.window, "menu_show_indentation_guides1")), editor_prefs.show_indent_guide);
|
2008-12-07 19:12:08 +00:00
|
|
|
ignore_callback = FALSE;
|
2006-09-05 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-24 12:01:30 +00:00
|
|
|
/** Creates a GNOME HIG-style frame (with no border and indented child alignment).
|
|
|
|
* @param label_text The label text.
|
|
|
|
* @param alignment An address to store the alignment widget pointer.
|
|
|
|
* @return The frame widget, setting the alignment container for packing child widgets. */
|
2006-11-24 11:11:06 +00:00
|
|
|
GtkWidget *ui_frame_new_with_alignment(const gchar *label_text, GtkWidget **alignment)
|
2006-09-15 14:25:42 +00:00
|
|
|
{
|
|
|
|
GtkWidget *label, *align;
|
2009-09-21 16:21:03 +00:00
|
|
|
GtkWidget *frame = gtk_frame_new(NULL);
|
2006-09-15 14:25:42 +00:00
|
|
|
|
2009-09-21 16:21:03 +00:00
|
|
|
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
|
2006-09-15 14:25:42 +00:00
|
|
|
|
2009-09-21 16:21:03 +00:00
|
|
|
align = gtk_alignment_new(0.5, 0.5, 1, 1);
|
|
|
|
gtk_container_add(GTK_CONTAINER(frame), align);
|
|
|
|
gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 12, 0);
|
2006-09-15 14:25:42 +00:00
|
|
|
|
2009-09-21 16:21:03 +00:00
|
|
|
label = ui_label_new_bold(label_text);
|
|
|
|
gtk_frame_set_label_widget(GTK_FRAME(frame), label);
|
2006-09-15 14:25:42 +00:00
|
|
|
|
2006-11-24 11:11:06 +00:00
|
|
|
*alignment = align;
|
|
|
|
return frame;
|
2006-09-15 14:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-12 18:15:48 +00:00
|
|
|
/** Makes a fixed border for dialogs without increasing the button box border.
|
2008-07-24 12:01:30 +00:00
|
|
|
* @param dialog The parent container for the @c GtkVBox.
|
|
|
|
* @return The packed @c GtkVBox. */
|
2006-10-22 14:56:05 +00:00
|
|
|
GtkWidget *ui_dialog_vbox_new(GtkDialog *dialog)
|
|
|
|
{
|
2008-02-27 13:17:29 +00:00
|
|
|
GtkWidget *vbox = gtk_vbox_new(FALSE, 12); /* need child vbox to set a separate border. */
|
2006-10-22 14:56:05 +00:00
|
|
|
|
2009-10-21 11:59:33 +00:00
|
|
|
gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
|
2006-10-22 14:56:05 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
|
|
|
|
return vbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-12 11:23:22 +00:00
|
|
|
/** Creates a @c GtkButton with custom text and a stock image similar to
|
2008-07-24 12:01:30 +00:00
|
|
|
* @c gtk_button_new_from_stock().
|
|
|
|
* @param stock_id A @c GTK_STOCK_NAME string.
|
|
|
|
* @param text Button label text, can include mnemonics.
|
|
|
|
* @return The new @c GtkButton.
|
|
|
|
*/
|
2006-11-01 15:26:41 +00:00
|
|
|
GtkWidget *ui_button_new_with_image(const gchar *stock_id, const gchar *text)
|
|
|
|
{
|
2010-03-12 11:23:22 +00:00
|
|
|
GtkWidget *image, *button;
|
2006-11-01 15:26:41 +00:00
|
|
|
|
2010-03-12 11:23:22 +00:00
|
|
|
button = gtk_button_new_with_mnemonic(text);
|
|
|
|
gtk_widget_show(button);
|
2006-11-01 15:26:41 +00:00
|
|
|
image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_BUTTON);
|
2010-03-12 11:23:22 +00:00
|
|
|
gtk_button_set_image(GTK_BUTTON(button), image);
|
|
|
|
/* note: image is shown by gtk */
|
2006-11-01 15:26:41 +00:00
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-12 18:15:48 +00:00
|
|
|
/** Creates a @c GtkImageMenuItem with a stock image and a custom label.
|
2008-11-21 13:34:58 +00:00
|
|
|
* @param stock_id Stock image ID, e.g. @c GTK_STOCK_OPEN.
|
|
|
|
* @param label Menu item label, can include mnemonics.
|
2009-01-30 18:53:23 +00:00
|
|
|
* @return The new @c GtkImageMenuItem.
|
|
|
|
*
|
|
|
|
* @since 0.16
|
|
|
|
*/
|
2008-11-21 13:34:58 +00:00
|
|
|
GtkWidget *
|
|
|
|
ui_image_menu_item_new(const gchar *stock_id, const gchar *label)
|
|
|
|
{
|
|
|
|
GtkWidget *item = gtk_image_menu_item_new_with_mnemonic(label);
|
|
|
|
GtkWidget *image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU);
|
|
|
|
|
|
|
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
|
|
|
|
gtk_widget_show(image);
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-10 17:44:14 +00:00
|
|
|
static void entry_clear_icon_release_cb(GtkEntry *entry, gint icon_pos,
|
|
|
|
GdkEvent *event, gpointer data)
|
2009-01-27 19:31:45 +00:00
|
|
|
{
|
2009-04-15 22:47:33 +00:00
|
|
|
if (event->button.button == 1 && icon_pos == 1)
|
2009-01-27 19:31:45 +00:00
|
|
|
{
|
|
|
|
gtk_entry_set_text(entry, "");
|
2009-09-17 18:08:21 +00:00
|
|
|
gtk_widget_grab_focus(GTK_WIDGET(entry));
|
2009-01-27 19:31:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-12 18:15:48 +00:00
|
|
|
/** Adds a small clear icon to the right end of the passed @a entry.
|
2009-01-27 19:31:45 +00:00
|
|
|
* A callback to clear the contents of the GtkEntry is automatically added.
|
|
|
|
*
|
|
|
|
* This feature is only available with GTK 2.16 but implemented as a runtime check,
|
|
|
|
* so it is safe to just use this function, if the code is ran with older versions,
|
|
|
|
* nothing happens. If ran with GTK 2.16 or newer, the icon is displayed.
|
|
|
|
*
|
|
|
|
* @param entry The GtkEntry object to which the icon should be attached.
|
2009-01-30 18:53:23 +00:00
|
|
|
*
|
|
|
|
* @since 0.16
|
2009-01-27 19:31:45 +00:00
|
|
|
*/
|
2009-09-21 16:46:16 +00:00
|
|
|
void ui_entry_add_clear_icon(GtkEntry *entry)
|
2009-01-27 19:31:45 +00:00
|
|
|
{
|
|
|
|
if (gtk_check_version(2, 15, 2) == NULL)
|
|
|
|
{
|
|
|
|
g_object_set(entry, "secondary-icon-stock", "gtk-clear", NULL);
|
2009-05-10 17:44:14 +00:00
|
|
|
g_signal_connect(entry, "icon-release", G_CALLBACK(entry_clear_icon_release_cb), NULL);
|
2009-01-27 19:31:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-01 15:26:41 +00:00
|
|
|
static void add_to_size_group(GtkWidget *widget, gpointer size_group)
|
|
|
|
{
|
|
|
|
g_return_if_fail(GTK_IS_SIZE_GROUP(size_group));
|
|
|
|
gtk_size_group_add_widget(GTK_SIZE_GROUP(size_group), widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Copies the spacing and layout of the master GtkHButtonBox and synchronises
|
|
|
|
* the width of each button box's children.
|
|
|
|
* Should be called after all child widgets have been packed. */
|
|
|
|
void ui_hbutton_box_copy_layout(GtkButtonBox *master, GtkButtonBox *copy)
|
|
|
|
{
|
|
|
|
GtkSizeGroup *size_group;
|
|
|
|
|
2008-10-22 15:36:45 +00:00
|
|
|
gtk_box_set_spacing(GTK_BOX(copy), 10);
|
2006-11-01 15:26:41 +00:00
|
|
|
gtk_button_box_set_layout(copy, gtk_button_box_get_layout(master));
|
|
|
|
|
|
|
|
/* now we need to put the widest widget from each button box in a size group,
|
|
|
|
* but we don't know the width before they are drawn, and for different label
|
|
|
|
* translations the widest widget can vary, so we just add all widgets. */
|
|
|
|
size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
|
|
|
|
gtk_container_foreach(GTK_CONTAINER(master), add_to_size_group, size_group);
|
|
|
|
gtk_container_foreach(GTK_CONTAINER(copy), add_to_size_group, size_group);
|
|
|
|
g_object_unref(size_group);
|
|
|
|
}
|
|
|
|
|
2006-09-05 14:24:47 +00:00
|
|
|
|
2010-06-17 17:28:28 +00:00
|
|
|
static gboolean tree_model_find_text(GtkTreeModel *model,
|
|
|
|
GtkTreeIter *iter, gint column, const gchar *text)
|
|
|
|
{
|
|
|
|
gchar *combo_text;
|
|
|
|
gboolean found = FALSE;
|
|
|
|
|
|
|
|
if (gtk_tree_model_get_iter_first(model, iter))
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
gtk_tree_model_get(model, iter, 0, &combo_text, -1);
|
|
|
|
found = utils_str_equal(combo_text, text);
|
|
|
|
g_free(combo_text);
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
while (gtk_tree_model_iter_next(model, iter));
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-18 12:20:15 +00:00
|
|
|
/** Prepends @a text to the drop down list, removing a duplicate element in
|
|
|
|
* the list if found. Also ensures there are <= @a history_len elements.
|
|
|
|
* @param combo_entry .
|
|
|
|
* @param text Text to add, or @c NULL for current entry text.
|
|
|
|
* @param history_len Max number of items, or @c 0 for default. */
|
|
|
|
void ui_combo_box_add_to_history(GtkComboBoxEntry *combo_entry,
|
|
|
|
const gchar *text, gint history_len)
|
2006-11-15 15:57:23 +00:00
|
|
|
{
|
2010-06-18 12:20:15 +00:00
|
|
|
GtkComboBox *combo = GTK_COMBO_BOX(combo_entry);
|
2006-11-15 15:57:23 +00:00
|
|
|
GtkTreeModel *model;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
GtkTreePath *path;
|
|
|
|
|
2010-06-18 12:20:15 +00:00
|
|
|
if (history_len <= 0)
|
|
|
|
history_len = 10;
|
|
|
|
if (!text)
|
|
|
|
text = gtk_entry_get_text(GTK_ENTRY(GTK_BIN(combo)->child));
|
|
|
|
|
2006-11-15 15:57:23 +00:00
|
|
|
model = gtk_combo_box_get_model(combo);
|
2010-06-17 17:28:28 +00:00
|
|
|
|
|
|
|
if (tree_model_find_text(model, &iter, 0, text))
|
2006-11-15 15:57:23 +00:00
|
|
|
{
|
2010-06-17 17:28:28 +00:00
|
|
|
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
|
2006-11-15 15:57:23 +00:00
|
|
|
}
|
|
|
|
gtk_combo_box_prepend_text(combo, text);
|
2006-12-01 18:44:35 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* limit history */
|
2006-11-15 15:57:23 +00:00
|
|
|
path = gtk_tree_path_new_from_indices(history_len, -1);
|
|
|
|
if (gtk_tree_model_get_iter(model, &iter, path))
|
|
|
|
{
|
|
|
|
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
|
|
|
|
}
|
|
|
|
gtk_tree_path_free(path);
|
|
|
|
}
|
|
|
|
|
2006-12-05 10:37:36 +00:00
|
|
|
|
2008-11-16 17:53:55 +00:00
|
|
|
/* Same as gtk_combo_box_prepend_text(), except that text is only prepended if it not already
|
|
|
|
* exists in the combo's model. */
|
|
|
|
void ui_combo_box_prepend_text_once(GtkComboBox *combo, const gchar *text)
|
|
|
|
{
|
|
|
|
GtkTreeModel *model;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
|
|
|
|
model = gtk_combo_box_get_model(combo);
|
2010-07-02 12:19:00 +00:00
|
|
|
if (tree_model_find_text(model, &iter, 0, text))
|
2008-11-16 17:53:55 +00:00
|
|
|
return; /* don't prepend duplicate */
|
|
|
|
|
|
|
|
gtk_combo_box_prepend_text(combo, text);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-05 10:37:36 +00:00
|
|
|
/* Changes the color of the notebook tab text and open files items according to
|
|
|
|
* document status. */
|
2008-06-15 13:35:48 +00:00
|
|
|
void ui_update_tab_status(GeanyDocument *doc)
|
2006-12-05 10:37:36 +00:00
|
|
|
{
|
2009-02-08 19:52:21 +00:00
|
|
|
const GdkColor *color = document_get_status_color(doc);
|
2006-12-05 10:37:36 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* NULL color will reset to default */
|
2008-09-26 17:28:50 +00:00
|
|
|
gtk_widget_modify_fg(doc->priv->tab_label, GTK_STATE_NORMAL, color);
|
|
|
|
gtk_widget_modify_fg(doc->priv->tab_label, GTK_STATE_ACTIVE, color);
|
2006-12-05 10:37:36 +00:00
|
|
|
|
2009-09-28 11:16:59 +00:00
|
|
|
sidebar_openfiles_update(doc);
|
2006-12-05 10:37:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-25 17:38:31 +00:00
|
|
|
static gboolean tree_model_iter_get_next(GtkTreeModel *model, GtkTreeIter *iter,
|
|
|
|
gboolean down)
|
|
|
|
{
|
|
|
|
GtkTreePath *path;
|
|
|
|
gboolean result;
|
|
|
|
|
|
|
|
if (down)
|
|
|
|
return gtk_tree_model_iter_next(model, iter);
|
|
|
|
|
|
|
|
path = gtk_tree_model_get_path(model, iter);
|
|
|
|
result = gtk_tree_path_prev(path) && gtk_tree_model_get_iter(model, iter, path);
|
|
|
|
gtk_tree_path_free(path);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* note: the while loop might be more efficient when searching upwards if it
|
|
|
|
* used tree paths instead of tree iters, but in practice it probably doesn't matter much. */
|
|
|
|
static gboolean tree_view_find(GtkTreeView *treeview, TVMatchCallback cb, gboolean down)
|
2006-12-08 15:50:10 +00:00
|
|
|
{
|
|
|
|
GtkTreeSelection *treesel;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
GtkTreeModel *model;
|
|
|
|
|
|
|
|
treesel = gtk_tree_view_get_selection(treeview);
|
|
|
|
if (gtk_tree_selection_get_selected(treesel, &model, &iter))
|
|
|
|
{
|
2008-02-27 13:17:29 +00:00
|
|
|
/* get the next selected item */
|
2008-06-25 17:38:31 +00:00
|
|
|
if (! tree_model_iter_get_next(model, &iter, down))
|
2008-02-27 13:17:29 +00:00
|
|
|
return FALSE; /* no more items */
|
2006-12-08 15:50:10 +00:00
|
|
|
}
|
2008-02-27 13:17:29 +00:00
|
|
|
else /* no selection */
|
2006-12-08 15:50:10 +00:00
|
|
|
{
|
|
|
|
if (! gtk_tree_model_get_iter_first(model, &iter))
|
2008-02-27 13:17:29 +00:00
|
|
|
return TRUE; /* no items */
|
2006-12-08 15:50:10 +00:00
|
|
|
}
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
gtk_tree_selection_select_iter(treesel, &iter);
|
2010-02-28 14:57:06 +00:00
|
|
|
if (cb(0))
|
2008-02-27 13:17:29 +00:00
|
|
|
break; /* found next message */
|
2006-12-08 15:50:10 +00:00
|
|
|
|
2008-06-25 17:38:31 +00:00
|
|
|
if (! tree_model_iter_get_next(model, &iter, down))
|
2008-02-27 13:17:29 +00:00
|
|
|
return FALSE; /* no more items */
|
2006-12-08 15:50:10 +00:00
|
|
|
}
|
2008-02-27 13:17:29 +00:00
|
|
|
/* scroll item in view */
|
2007-08-23 11:34:06 +00:00
|
|
|
if (ui_prefs.msgwindow_visible)
|
2007-02-17 16:52:52 +00:00
|
|
|
{
|
|
|
|
GtkTreePath *path = gtk_tree_model_get_path(
|
|
|
|
gtk_tree_view_get_model(treeview), &iter);
|
|
|
|
|
|
|
|
gtk_tree_view_scroll_to_cell(treeview, path, NULL, TRUE, 0.5, 0.5);
|
|
|
|
gtk_tree_path_free(path);
|
|
|
|
}
|
2006-12-08 15:50:10 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-25 17:38:31 +00:00
|
|
|
/* Returns FALSE if the treeview has items but no matching next item. */
|
|
|
|
gboolean ui_tree_view_find_next(GtkTreeView *treeview, TVMatchCallback cb)
|
|
|
|
{
|
|
|
|
return tree_view_find(treeview, cb, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Returns FALSE if the treeview has items but no matching next item. */
|
|
|
|
gboolean ui_tree_view_find_previous(GtkTreeView *treeview, TVMatchCallback cb)
|
|
|
|
{
|
|
|
|
return tree_view_find(treeview, cb, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-25 22:43:15 +00:00
|
|
|
/**
|
|
|
|
* Modifies the font of a widget using gtk_widget_modify_font().
|
|
|
|
*
|
|
|
|
* @param widget The widget.
|
|
|
|
* @param str The font name as expected by pango_font_description_from_string().
|
|
|
|
*/
|
|
|
|
void ui_widget_modify_font_from_string(GtkWidget *widget, const gchar *str)
|
2006-12-13 15:18:49 +00:00
|
|
|
{
|
|
|
|
PangoFontDescription *pfd;
|
|
|
|
|
|
|
|
pfd = pango_font_description_from_string(str);
|
2009-10-25 22:43:15 +00:00
|
|
|
gtk_widget_modify_font(widget, pfd);
|
2006-12-13 15:18:49 +00:00
|
|
|
pango_font_description_free(pfd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-24 12:01:30 +00:00
|
|
|
/** Creates a @c GtkHBox with @a entry packed into it and an open button which runs a
|
|
|
|
* file chooser, replacing entry text (if successful) with the path returned from the
|
|
|
|
* @c GtkFileChooser.
|
|
|
|
* @note @a entry can be the child of an unparented widget, such as @c GtkComboBoxEntry.
|
|
|
|
* @param title The file chooser dialog title, or @c NULL.
|
|
|
|
* @param action The mode of the file chooser.
|
|
|
|
* @param entry Can be an unpacked @c GtkEntry, or the child of an unpacked widget,
|
|
|
|
* such as @c GtkComboBoxEntry.
|
|
|
|
* @return The @c GtkHBox.
|
|
|
|
*/
|
|
|
|
/* @see ui_setup_open_button_callback(). */
|
2007-05-11 16:34:18 +00:00
|
|
|
GtkWidget *ui_path_box_new(const gchar *title, GtkFileChooserAction action, GtkEntry *entry)
|
2007-04-29 12:03:25 +00:00
|
|
|
{
|
|
|
|
GtkWidget *vbox, *dirbtn, *openimg, *hbox, *path_entry;
|
|
|
|
|
|
|
|
hbox = gtk_hbox_new(FALSE, 6);
|
|
|
|
path_entry = GTK_WIDGET(entry);
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* prevent path_entry being vertically stretched to the height of dirbtn */
|
2007-04-29 12:03:25 +00:00
|
|
|
vbox = gtk_vbox_new(FALSE, 0);
|
2008-02-27 13:17:29 +00:00
|
|
|
if (gtk_widget_get_parent(path_entry)) /* entry->parent may be a GtkComboBoxEntry */
|
2007-04-29 12:03:25 +00:00
|
|
|
{
|
|
|
|
GtkWidget *parent = gtk_widget_get_parent(path_entry);
|
|
|
|
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), parent, TRUE, FALSE, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), path_entry, TRUE, FALSE, 0);
|
|
|
|
|
|
|
|
dirbtn = gtk_button_new();
|
|
|
|
openimg = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);
|
|
|
|
gtk_container_add(GTK_CONTAINER(dirbtn), openimg);
|
2007-05-11 16:34:18 +00:00
|
|
|
ui_setup_open_button_callback(dirbtn, title, action, entry);
|
2007-04-29 12:03:25 +00:00
|
|
|
|
|
|
|
gtk_box_pack_end(GTK_BOX(hbox), dirbtn, FALSE, FALSE, 0);
|
|
|
|
gtk_box_pack_end(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
|
|
|
|
return hbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void ui_path_box_open_clicked(GtkButton *button, gpointer user_data);
|
|
|
|
|
|
|
|
|
|
|
|
/* Setup a GtkButton to run a GtkFileChooser, setting entry text if successful.
|
2007-05-11 16:34:18 +00:00
|
|
|
* title can be NULL.
|
2007-04-29 12:03:25 +00:00
|
|
|
* action is the file chooser mode to use. */
|
2007-05-11 16:34:18 +00:00
|
|
|
void ui_setup_open_button_callback(GtkWidget *open_btn, const gchar *title,
|
|
|
|
GtkFileChooserAction action, GtkEntry *entry)
|
2007-04-29 12:03:25 +00:00
|
|
|
{
|
|
|
|
GtkWidget *path_entry = GTK_WIDGET(entry);
|
|
|
|
|
2007-05-11 16:34:18 +00:00
|
|
|
if (title)
|
2008-07-18 13:40:48 +00:00
|
|
|
g_object_set_data_full(G_OBJECT(open_btn), "title", g_strdup(title),
|
|
|
|
(GDestroyNotify) g_free);
|
2007-04-29 12:03:25 +00:00
|
|
|
g_object_set_data(G_OBJECT(open_btn), "action", (gpointer) action);
|
2010-06-23 16:57:28 +00:00
|
|
|
ui_hookup_widget(open_btn, path_entry, "entry");
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(open_btn, "clicked", G_CALLBACK(ui_path_box_open_clicked), open_btn);
|
2007-04-29 12:03:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-11 16:34:18 +00:00
|
|
|
#ifndef G_OS_WIN32
|
|
|
|
static gchar *run_file_chooser(const gchar *title, GtkFileChooserAction action,
|
|
|
|
const gchar *utf8_path)
|
2007-04-29 12:03:25 +00:00
|
|
|
{
|
|
|
|
GtkWidget *dialog = gtk_file_chooser_dialog_new(title,
|
2008-05-22 14:41:28 +00:00
|
|
|
GTK_WINDOW(main_widgets.window), action,
|
2007-04-29 12:03:25 +00:00
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
|
|
GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
|
|
|
|
gchar *locale_path;
|
2007-05-11 16:34:18 +00:00
|
|
|
gchar *ret_path = NULL;
|
2007-04-29 12:03:25 +00:00
|
|
|
|
2007-05-15 15:16:16 +00:00
|
|
|
gtk_widget_set_name(dialog, "GeanyDialog");
|
2007-04-29 12:03:25 +00:00
|
|
|
locale_path = utils_get_locale_from_utf8(utf8_path);
|
2009-04-15 22:47:33 +00:00
|
|
|
if (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
2007-04-29 12:03:25 +00:00
|
|
|
{
|
|
|
|
if (g_path_is_absolute(locale_path) && g_file_test(locale_path, G_FILE_TEST_IS_DIR))
|
|
|
|
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), locale_path);
|
|
|
|
}
|
2009-11-17 21:47:06 +00:00
|
|
|
else if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
|
|
|
|
{
|
|
|
|
if (g_path_is_absolute(locale_path))
|
|
|
|
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), locale_path);
|
|
|
|
}
|
2007-04-29 12:03:25 +00:00
|
|
|
g_free(locale_path);
|
|
|
|
|
|
|
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
|
|
|
|
{
|
2007-05-11 16:34:18 +00:00
|
|
|
gchar *dir_locale;
|
|
|
|
|
2009-03-16 13:45:12 +00:00
|
|
|
dir_locale = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
2007-05-11 16:34:18 +00:00
|
|
|
ret_path = utils_get_utf8_from_locale(dir_locale);
|
2007-04-29 12:03:25 +00:00
|
|
|
g_free(dir_locale);
|
|
|
|
}
|
|
|
|
gtk_widget_destroy(dialog);
|
2007-05-11 16:34:18 +00:00
|
|
|
return ret_path;
|
2007-04-29 12:03:25 +00:00
|
|
|
}
|
2007-05-11 16:34:18 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static void ui_path_box_open_clicked(GtkButton *button, gpointer user_data)
|
|
|
|
{
|
|
|
|
GtkWidget *path_box = GTK_WIDGET(user_data);
|
|
|
|
GtkFileChooserAction action =
|
|
|
|
(GtkFileChooserAction) g_object_get_data(G_OBJECT(path_box), "action");
|
|
|
|
GtkEntry *entry =
|
|
|
|
(GtkEntry *) g_object_get_data(G_OBJECT(path_box), "entry");
|
|
|
|
const gchar *title = g_object_get_data(G_OBJECT(path_box), "title");
|
2009-11-30 22:58:57 +00:00
|
|
|
gchar *utf8_path = NULL;
|
2007-05-11 16:34:18 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* TODO: extend for other actions */
|
2009-11-17 21:47:06 +00:00
|
|
|
g_return_if_fail(action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
|
|
|
|
action == GTK_FILE_CHOOSER_ACTION_OPEN);
|
2007-05-11 16:34:18 +00:00
|
|
|
|
|
|
|
if (title == NULL)
|
|
|
|
title = (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ?
|
|
|
|
_("Select Folder") : _("Select File");
|
|
|
|
|
2009-11-17 21:47:06 +00:00
|
|
|
if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
|
|
|
|
{
|
2007-05-11 16:34:18 +00:00
|
|
|
#ifdef G_OS_WIN32
|
2009-12-20 21:49:23 +00:00
|
|
|
utf8_path = win32_show_file_dialog(GTK_WINDOW(ui_widgets.prefs_dialog), title,
|
2007-05-11 16:34:18 +00:00
|
|
|
gtk_entry_get_text(GTK_ENTRY(entry)));
|
|
|
|
#else
|
2009-11-17 21:47:06 +00:00
|
|
|
utf8_path = run_file_chooser(title, action, gtk_entry_get_text(GTK_ENTRY(entry)));
|
2007-05-11 16:34:18 +00:00
|
|
|
#endif
|
2009-11-17 21:47:06 +00:00
|
|
|
}
|
|
|
|
else if (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
|
|
|
{
|
|
|
|
gchar *path = g_path_get_dirname(gtk_entry_get_text(GTK_ENTRY(entry)));
|
|
|
|
#ifdef G_OS_WIN32
|
2009-12-20 21:49:23 +00:00
|
|
|
utf8_path = win32_show_folder_dialog(ui_widgets.prefs_dialog, title,
|
|
|
|
gtk_entry_get_text(GTK_ENTRY(entry)));
|
2009-11-17 21:47:06 +00:00
|
|
|
#else
|
|
|
|
utf8_path = run_file_chooser(title, action, path);
|
|
|
|
#endif
|
|
|
|
g_free(path);
|
|
|
|
}
|
2007-05-11 16:34:18 +00:00
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
if (utf8_path != NULL)
|
2007-05-11 16:34:18 +00:00
|
|
|
{
|
|
|
|
gtk_entry_set_text(GTK_ENTRY(entry), utf8_path);
|
|
|
|
g_free(utf8_path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-29 12:03:25 +00:00
|
|
|
|
2007-05-04 16:59:00 +00:00
|
|
|
void ui_statusbar_showhide(gboolean state)
|
|
|
|
{
|
2008-02-27 13:17:29 +00:00
|
|
|
/* handle statusbar visibility */
|
2007-05-04 16:59:00 +00:00
|
|
|
if (state)
|
|
|
|
{
|
2008-05-22 14:41:28 +00:00
|
|
|
gtk_widget_show(ui_widgets.statusbar);
|
2008-06-15 13:35:48 +00:00
|
|
|
ui_update_statusbar(NULL, -1);
|
2007-05-04 16:59:00 +00:00
|
|
|
}
|
|
|
|
else
|
2008-05-22 14:41:28 +00:00
|
|
|
gtk_widget_hide(ui_widgets.statusbar);
|
2007-05-04 16:59:00 +00:00
|
|
|
}
|
2007-07-13 15:54:16 +00:00
|
|
|
|
|
|
|
|
2010-03-12 18:15:48 +00:00
|
|
|
/** Packs all @c GtkWidgets passed after the row argument into a table, using
|
2008-07-24 12:01:30 +00:00
|
|
|
* one widget per cell. The first widget is not expanded as the table grows,
|
|
|
|
* as this is usually a label.
|
|
|
|
* @param table
|
|
|
|
* @param row The row number of the table.
|
|
|
|
*/
|
2007-07-13 15:54:16 +00:00
|
|
|
void ui_table_add_row(GtkTable *table, gint row, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
gint i;
|
|
|
|
GtkWidget *widget;
|
|
|
|
|
|
|
|
va_start(args, row);
|
|
|
|
for (i = 0; (widget = va_arg(args, GtkWidget*), widget != NULL); i++)
|
|
|
|
{
|
|
|
|
gint options = (i == 0) ? GTK_FILL : GTK_EXPAND | GTK_FILL;
|
|
|
|
|
|
|
|
gtk_table_attach(GTK_TABLE(table), widget, i, i + 1, row, row + 1,
|
|
|
|
options, 0, 0, 0);
|
|
|
|
}
|
|
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-26 13:15:53 +00:00
|
|
|
static void on_config_file_clicked(GtkWidget *widget, gpointer user_data)
|
|
|
|
{
|
|
|
|
const gchar *file_name = user_data;
|
2009-06-09 14:39:28 +00:00
|
|
|
GeanyFiletype *ft = NULL;
|
|
|
|
|
|
|
|
if (strstr(file_name, G_DIR_SEPARATOR_S "filetypes."))
|
|
|
|
ft = filetypes[GEANY_FILETYPES_CONF];
|
2008-11-26 13:15:53 +00:00
|
|
|
|
|
|
|
if (g_file_test(file_name, G_FILE_TEST_EXISTS))
|
2009-06-09 14:39:28 +00:00
|
|
|
document_open_file(file_name, FALSE, ft, NULL);
|
2008-11-26 13:15:53 +00:00
|
|
|
else
|
|
|
|
{
|
2010-03-07 17:37:00 +00:00
|
|
|
gchar *utf8_filename = utils_get_utf8_from_locale(file_name);
|
2008-12-06 12:28:21 +00:00
|
|
|
gchar *base_name = g_path_get_basename(file_name);
|
|
|
|
gchar *global_file = g_build_filename(app->datadir, base_name, NULL);
|
|
|
|
gchar *global_content = NULL;
|
2008-11-26 13:15:53 +00:00
|
|
|
|
2008-12-06 12:28:21 +00:00
|
|
|
/* if the requested file doesn't exist in the user's config dir, try loading the file
|
|
|
|
* from the global data directory and use its contents for the newly created file */
|
|
|
|
if (g_file_test(global_file, G_FILE_TEST_EXISTS))
|
|
|
|
g_file_get_contents(global_file, &global_content, NULL, NULL);
|
|
|
|
|
2010-03-15 14:05:42 +00:00
|
|
|
document_new_file(utf8_filename, ft, global_content);
|
2010-03-07 17:37:00 +00:00
|
|
|
|
|
|
|
utils_free_pointers(4, utf8_filename, base_name, global_file, global_content, NULL);
|
2008-11-26 13:15:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* @note You should connect to the "document-save" signal yourself to detect
|
|
|
|
* if the user has just saved the config file, reloading it. */
|
2008-12-06 11:10:06 +00:00
|
|
|
void ui_add_config_file_menu_item(const gchar *real_path, const gchar *label, GtkContainer *parent)
|
2008-11-26 13:15:53 +00:00
|
|
|
{
|
|
|
|
GtkWidget *item;
|
|
|
|
|
|
|
|
if (!parent)
|
|
|
|
parent = GTK_CONTAINER(widgets.config_files_menu);
|
|
|
|
|
|
|
|
if (!label)
|
|
|
|
{
|
|
|
|
gchar *base_name;
|
|
|
|
|
|
|
|
base_name = g_path_get_basename(real_path);
|
|
|
|
item = gtk_menu_item_new_with_label(base_name);
|
|
|
|
g_free(base_name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
item = gtk_menu_item_new_with_mnemonic(label);
|
|
|
|
|
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(parent, item);
|
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_config_file_clicked),
|
|
|
|
/* this memory is kept */
|
|
|
|
g_strdup(real_path));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-08 12:25:47 +00:00
|
|
|
static gboolean sort_menu(gpointer data)
|
|
|
|
{
|
|
|
|
ui_menu_sort_by_label(GTK_MENU(data));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-26 13:15:53 +00:00
|
|
|
static void create_config_files_menu(void)
|
|
|
|
{
|
|
|
|
GtkWidget *menu, *item;
|
|
|
|
|
|
|
|
widgets.config_files_menu = menu = gtk_menu_new();
|
|
|
|
|
2009-10-14 13:51:43 +00:00
|
|
|
item = ui_lookup_widget(main_widgets.window, "configuration_files1");
|
2008-11-26 13:15:53 +00:00
|
|
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
|
2009-04-08 12:25:47 +00:00
|
|
|
|
|
|
|
/* sort menu after all items added */
|
|
|
|
g_idle_add(sort_menu, widgets.config_files_menu);
|
2008-11-26 13:15:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-20 16:53:28 +00:00
|
|
|
void ui_init_stock_items(void)
|
2008-12-06 11:45:48 +00:00
|
|
|
{
|
|
|
|
GtkIconSet *icon_set;
|
|
|
|
GtkIconFactory *factory = gtk_icon_factory_new();
|
|
|
|
GdkPixbuf *pb;
|
2008-12-06 12:28:21 +00:00
|
|
|
gsize i, len;
|
2008-12-09 20:31:38 +00:00
|
|
|
GtkStockItem items[] =
|
2008-12-06 11:45:48 +00:00
|
|
|
{
|
2008-12-09 20:31:38 +00:00
|
|
|
{ GEANY_STOCK_SAVE_ALL, _("Save All"), 0, 0, GETTEXT_PACKAGE },
|
2009-01-17 17:59:20 +00:00
|
|
|
{ GEANY_STOCK_CLOSE_ALL, _("Close All"), 0, 0, GETTEXT_PACKAGE },
|
|
|
|
{ GEANY_STOCK_BUILD, _("Build"), 0, 0, GETTEXT_PACKAGE }
|
2008-12-06 11:45:48 +00:00
|
|
|
};
|
|
|
|
|
2008-12-06 12:28:21 +00:00
|
|
|
len = G_N_ELEMENTS(items);
|
|
|
|
for (i = 0; i < len; i++)
|
2008-12-06 11:45:48 +00:00
|
|
|
{
|
2008-12-09 20:31:38 +00:00
|
|
|
pb = ui_new_pixbuf_from_stock(items[i].stock_id);
|
2008-12-06 11:45:48 +00:00
|
|
|
icon_set = gtk_icon_set_new_from_pixbuf(pb);
|
|
|
|
|
2008-12-09 20:31:38 +00:00
|
|
|
gtk_icon_factory_add(factory, items[i].stock_id, icon_set);
|
2008-12-06 11:45:48 +00:00
|
|
|
|
|
|
|
gtk_icon_set_unref(icon_set);
|
|
|
|
g_object_unref(pb);
|
|
|
|
}
|
2008-12-06 12:28:21 +00:00
|
|
|
gtk_stock_add((GtkStockItem *) items, len);
|
2008-12-06 11:45:48 +00:00
|
|
|
gtk_icon_factory_add_default(factory);
|
|
|
|
g_object_unref(factory);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-20 16:51:32 +00:00
|
|
|
void ui_init_toolbar_widgets(void)
|
|
|
|
{
|
|
|
|
widgets.save_buttons[1] = toolbar_get_widget_by_name("Save");
|
|
|
|
widgets.save_buttons[3] = toolbar_get_widget_by_name("SaveAll");
|
|
|
|
widgets.redo_items[2] = toolbar_get_widget_by_name("Redo");
|
|
|
|
widgets.undo_items[2] = toolbar_get_widget_by_name("Undo");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-23 16:18:05 +00:00
|
|
|
void ui_swap_sidebar_pos(void)
|
|
|
|
{
|
|
|
|
GtkWidget *pane = ui_lookup_widget(main_widgets.window, "hpaned1");
|
|
|
|
GtkWidget *left = gtk_paned_get_child1(GTK_PANED(pane));
|
|
|
|
GtkWidget *right = gtk_paned_get_child2(GTK_PANED(pane));
|
|
|
|
GtkWidget *box = ui_lookup_widget(main_widgets.window, "vbox1");
|
|
|
|
|
|
|
|
/* reparenting avoids scintilla problem with middle click paste */
|
|
|
|
gtk_widget_reparent(left, box);
|
|
|
|
gtk_widget_reparent(right, box);
|
|
|
|
gtk_widget_reparent(right, pane);
|
|
|
|
gtk_widget_reparent(left, pane);
|
|
|
|
|
|
|
|
gtk_paned_set_position(GTK_PANED(pane), pane->allocation.width
|
|
|
|
- gtk_paned_get_position(GTK_PANED(pane)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-20 16:51:32 +00:00
|
|
|
static void init_recent_files(void)
|
|
|
|
{
|
|
|
|
GtkWidget *toolbar_recent_files_menu;
|
|
|
|
|
|
|
|
/* add recent files to the File menu */
|
|
|
|
ui_widgets.recent_files_menuitem = ui_lookup_widget(main_widgets.window, "recent_files1");
|
|
|
|
ui_widgets.recent_files_menu_menubar = gtk_menu_new();
|
|
|
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(ui_widgets.recent_files_menuitem),
|
|
|
|
ui_widgets.recent_files_menu_menubar);
|
|
|
|
|
|
|
|
/* add recent files to the toolbar Open button */
|
|
|
|
toolbar_recent_files_menu = gtk_menu_new();
|
|
|
|
g_object_ref(toolbar_recent_files_menu);
|
|
|
|
geany_menu_button_action_set_menu(GEANY_MENU_BUTTON_ACTION(
|
|
|
|
toolbar_get_action_by_name("Open")), toolbar_recent_files_menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-27 17:27:24 +00:00
|
|
|
static void ui_menu_move(GtkWidget *menu, GtkWidget *old, GtkWidget *new)
|
|
|
|
{
|
|
|
|
g_object_ref(menu);
|
|
|
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(old), NULL);
|
|
|
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(new), menu);
|
|
|
|
g_object_unref(menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-27 17:47:23 +00:00
|
|
|
static void on_editor_menu_show(GtkWidget *item)
|
2009-10-27 17:27:24 +00:00
|
|
|
{
|
|
|
|
GtkWidget *popup = ui_lookup_widget(main_widgets.editor_menu, "commands1");
|
|
|
|
GtkWidget *bar = ui_lookup_widget(main_widgets.window, "commands2");
|
|
|
|
|
2009-10-27 17:47:23 +00:00
|
|
|
ui_menu_move(widgets.commands_menu, bar, popup);
|
2009-10-27 18:10:39 +00:00
|
|
|
|
|
|
|
popup = ui_lookup_widget(main_widgets.editor_menu, "menu_format2");
|
|
|
|
bar = ui_lookup_widget(main_widgets.window, "menu_format1");
|
|
|
|
ui_menu_move(widgets.format_menu, bar, popup);
|
2009-10-27 17:27:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-27 17:47:23 +00:00
|
|
|
static void on_editor_menu_hide(GtkWidget *item)
|
2009-10-27 17:27:24 +00:00
|
|
|
{
|
|
|
|
GtkWidget *popup = ui_lookup_widget(main_widgets.editor_menu, "commands1");
|
|
|
|
GtkWidget *bar = ui_lookup_widget(main_widgets.window, "commands2");
|
|
|
|
|
2009-10-27 17:47:23 +00:00
|
|
|
ui_menu_move(widgets.commands_menu, popup, bar);
|
2009-10-27 18:10:39 +00:00
|
|
|
|
|
|
|
popup = ui_lookup_widget(main_widgets.editor_menu, "menu_format2");
|
|
|
|
bar = ui_lookup_widget(main_widgets.window, "menu_format1");
|
|
|
|
ui_menu_move(widgets.format_menu, popup, bar);
|
2009-10-27 17:27:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-09 17:15:16 +00:00
|
|
|
/* Currently ui_init() is called before keyfile.c stash group code is initialized,
|
|
|
|
* so this is called after that's done. */
|
|
|
|
void ui_init_prefs(void)
|
2010-06-29 12:11:21 +00:00
|
|
|
{
|
2010-07-09 17:15:16 +00:00
|
|
|
StashGroup *group = stash_group_new(PACKAGE);
|
2010-07-08 11:35:32 +00:00
|
|
|
|
2010-07-09 17:15:16 +00:00
|
|
|
configuration_add_pref_group(group, FALSE);
|
|
|
|
stash_group_set_write_once(group, TRUE);
|
2010-07-08 11:35:32 +00:00
|
|
|
|
2010-07-09 17:15:16 +00:00
|
|
|
stash_group_add_string(group, &statusbar_template, "statusbar_template", "");
|
2010-06-29 12:11:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
void ui_init(void)
|
2007-07-20 12:06:51 +00:00
|
|
|
{
|
2009-10-27 17:27:24 +00:00
|
|
|
GtkWidget *item;
|
|
|
|
|
2009-06-20 16:51:32 +00:00
|
|
|
init_recent_files();
|
|
|
|
|
2008-12-18 21:21:53 +00:00
|
|
|
ui_widgets.statusbar = ui_lookup_widget(main_widgets.window, "statusbar");
|
|
|
|
ui_widgets.print_page_setup = ui_lookup_widget(main_widgets.window, "page_setup1");
|
|
|
|
|
2009-01-27 20:19:43 +00:00
|
|
|
main_widgets.progressbar = progress_bar_create();
|
|
|
|
|
2008-12-18 21:21:53 +00:00
|
|
|
widgets.popup_goto_items[0] = ui_lookup_widget(main_widgets.editor_menu, "goto_tag_definition1");
|
|
|
|
widgets.popup_goto_items[1] = ui_lookup_widget(main_widgets.editor_menu, "goto_tag_declaration1");
|
|
|
|
widgets.popup_goto_items[2] = ui_lookup_widget(main_widgets.editor_menu, "find_usage1");
|
|
|
|
widgets.popup_goto_items[3] = ui_lookup_widget(main_widgets.editor_menu, "find_document_usage1");
|
|
|
|
widgets.popup_copy_items[0] = ui_lookup_widget(main_widgets.editor_menu, "cut1");
|
|
|
|
widgets.popup_copy_items[1] = ui_lookup_widget(main_widgets.editor_menu, "copy1");
|
|
|
|
widgets.popup_copy_items[2] = ui_lookup_widget(main_widgets.editor_menu, "delete1");
|
|
|
|
widgets.menu_copy_items[0] = ui_lookup_widget(main_widgets.window, "menu_cut1");
|
|
|
|
widgets.menu_copy_items[1] = ui_lookup_widget(main_widgets.window, "menu_copy1");
|
|
|
|
widgets.menu_copy_items[2] = ui_lookup_widget(main_widgets.window, "menu_delete1");
|
|
|
|
widgets.menu_insert_include_items[0] = ui_lookup_widget(main_widgets.editor_menu, "insert_include1");
|
|
|
|
widgets.menu_insert_include_items[1] = ui_lookup_widget(main_widgets.window, "insert_include2");
|
|
|
|
widgets.save_buttons[0] = ui_lookup_widget(main_widgets.window, "menu_save1");
|
|
|
|
widgets.save_buttons[2] = ui_lookup_widget(main_widgets.window, "menu_save_all1");
|
|
|
|
widgets.redo_items[0] = ui_lookup_widget(main_widgets.editor_menu, "redo1");
|
|
|
|
widgets.redo_items[1] = ui_lookup_widget(main_widgets.window, "menu_redo2");
|
|
|
|
widgets.undo_items[0] = ui_lookup_widget(main_widgets.editor_menu, "undo1");
|
|
|
|
widgets.undo_items[1] = ui_lookup_widget(main_widgets.window, "menu_undo2");
|
2008-07-17 16:28:16 +00:00
|
|
|
|
2009-10-27 18:10:39 +00:00
|
|
|
item = ui_lookup_widget(main_widgets.window, "menu_format1");
|
|
|
|
widgets.format_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item));
|
2009-10-27 17:47:23 +00:00
|
|
|
item = ui_lookup_widget(main_widgets.window, "commands2");
|
2009-10-27 17:27:24 +00:00
|
|
|
widgets.commands_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item));
|
|
|
|
|
|
|
|
/* reparent edit submenus as needed */
|
2009-10-27 17:47:23 +00:00
|
|
|
item = main_widgets.editor_menu;
|
|
|
|
g_signal_connect(item, "show", G_CALLBACK(on_editor_menu_show), NULL);
|
|
|
|
g_signal_connect(item, "hide", G_CALLBACK(on_editor_menu_hide), NULL);
|
2009-10-27 17:27:24 +00:00
|
|
|
|
2009-06-20 16:51:32 +00:00
|
|
|
ui_init_toolbar_widgets();
|
2007-07-20 12:06:51 +00:00
|
|
|
init_document_widgets();
|
2008-11-26 13:15:53 +00:00
|
|
|
create_config_files_menu();
|
2008-10-13 12:38:32 +00:00
|
|
|
}
|
|
|
|
|
2008-11-18 20:14:42 +00:00
|
|
|
|
2010-07-08 16:59:11 +00:00
|
|
|
void ui_finalize(void)
|
|
|
|
{
|
|
|
|
g_free(statusbar_template);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-11 16:56:28 +00:00
|
|
|
static void auto_separator_update(GeanyAutoSeparator *autosep)
|
|
|
|
{
|
2009-04-15 22:47:33 +00:00
|
|
|
g_return_if_fail(autosep->ref_count >= 0);
|
2008-12-11 16:56:28 +00:00
|
|
|
|
|
|
|
if (autosep->widget)
|
|
|
|
ui_widget_show_hide(autosep->widget, autosep->ref_count > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void on_auto_separator_item_show_hide(GtkWidget *widget, gpointer user_data)
|
|
|
|
{
|
|
|
|
GeanyAutoSeparator *autosep = user_data;
|
|
|
|
|
|
|
|
if (GTK_WIDGET_VISIBLE(widget))
|
|
|
|
autosep->ref_count++;
|
|
|
|
else
|
|
|
|
autosep->ref_count--;
|
|
|
|
auto_separator_update(autosep);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void on_auto_separator_item_destroy(GtkWidget *widget, gpointer user_data)
|
|
|
|
{
|
|
|
|
GeanyAutoSeparator *autosep = user_data;
|
|
|
|
|
|
|
|
/* GTK_WIDGET_VISIBLE won't work now the widget is being destroyed,
|
|
|
|
* so assume widget was visible */
|
|
|
|
autosep->ref_count--;
|
|
|
|
autosep->ref_count = MAX(autosep->ref_count, 0);
|
|
|
|
auto_separator_update(autosep);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Show the separator widget if @a item or another is visible. */
|
|
|
|
/* Note: This would be neater taking a widget argument, setting a "visible-count"
|
|
|
|
* property, and using reference counting to keep the widget alive whilst its visible group
|
|
|
|
* is alive. */
|
|
|
|
void ui_auto_separator_add_ref(GeanyAutoSeparator *autosep, GtkWidget *item)
|
|
|
|
{
|
|
|
|
/* set widget ptr NULL when widget destroyed */
|
|
|
|
if (autosep->ref_count == 0)
|
|
|
|
g_signal_connect(autosep->widget, "destroy",
|
|
|
|
G_CALLBACK(gtk_widget_destroyed), &autosep->widget);
|
|
|
|
|
|
|
|
if (GTK_WIDGET_VISIBLE(item))
|
|
|
|
{
|
|
|
|
autosep->ref_count++;
|
|
|
|
auto_separator_update(autosep);
|
|
|
|
}
|
|
|
|
g_signal_connect(item, "show", G_CALLBACK(on_auto_separator_item_show_hide), autosep);
|
|
|
|
g_signal_connect(item, "hide", G_CALLBACK(on_auto_separator_item_show_hide), autosep);
|
|
|
|
g_signal_connect(item, "destroy", G_CALLBACK(on_auto_separator_item_destroy), autosep);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-18 20:14:42 +00:00
|
|
|
/**
|
|
|
|
* Sets @a text as the contents of the tooltip for @a widget.
|
|
|
|
*
|
|
|
|
* @param widget The widget the tooltip should be set for.
|
|
|
|
* @param text The text for the tooltip.
|
2009-01-30 18:53:23 +00:00
|
|
|
*
|
|
|
|
* @since 0.16
|
2008-11-18 20:14:42 +00:00
|
|
|
*/
|
|
|
|
void ui_widget_set_tooltip_text(GtkWidget *widget, const gchar *text)
|
|
|
|
{
|
|
|
|
#if GTK_CHECK_VERSION(2, 12, 0)
|
|
|
|
gtk_widget_set_tooltip_text(widget, text);
|
|
|
|
#else
|
|
|
|
static GtkTooltips *tooltips = NULL;
|
|
|
|
|
2009-04-05 21:07:40 +00:00
|
|
|
if (G_UNLIKELY(tooltips == NULL))
|
2008-12-18 21:21:53 +00:00
|
|
|
tooltips = GTK_TOOLTIPS(ui_lookup_widget(main_widgets.window, "tooltips"));
|
2008-11-18 20:14:42 +00:00
|
|
|
|
|
|
|
gtk_tooltips_set_tip(tooltips, widget, text, NULL);
|
|
|
|
#endif
|
|
|
|
}
|
2008-12-02 18:33:41 +00:00
|
|
|
|
|
|
|
|
2010-03-12 18:15:48 +00:00
|
|
|
/** Returns a widget from a name in a component, usually created by Glade.
|
2008-12-02 18:33:41 +00:00
|
|
|
* Call it with the toplevel widget in the component (i.e. a window/dialog),
|
|
|
|
* or alternatively any widget in the component, and the name of the widget
|
|
|
|
* you want returned.
|
|
|
|
* @param widget Widget with the @a widget_name property set.
|
|
|
|
* @param widget_name Name to lookup.
|
2008-12-28 17:25:09 +00:00
|
|
|
* @return The widget found.
|
2009-01-30 18:53:23 +00:00
|
|
|
* @see ui_hookup_widget().
|
|
|
|
*
|
|
|
|
* @since 0.16
|
|
|
|
*/
|
2008-12-02 18:33:41 +00:00
|
|
|
GtkWidget *ui_lookup_widget(GtkWidget *widget, const gchar *widget_name)
|
|
|
|
{
|
2008-12-18 21:21:53 +00:00
|
|
|
GtkWidget *parent, *found_widget;
|
|
|
|
|
2009-04-15 22:47:33 +00:00
|
|
|
g_return_val_if_fail(widget != NULL, NULL);
|
|
|
|
g_return_val_if_fail(widget_name != NULL, NULL);
|
2009-04-05 14:13:56 +00:00
|
|
|
|
2008-12-18 21:21:53 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (GTK_IS_MENU(widget))
|
|
|
|
parent = gtk_menu_get_attach_widget(GTK_MENU(widget));
|
|
|
|
else
|
|
|
|
parent = widget->parent;
|
2009-04-15 22:47:33 +00:00
|
|
|
if (parent == NULL)
|
2008-12-18 21:21:53 +00:00
|
|
|
parent = (GtkWidget*) g_object_get_data(G_OBJECT(widget), "GladeParentKey");
|
|
|
|
if (parent == NULL)
|
|
|
|
break;
|
|
|
|
widget = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
found_widget = (GtkWidget*) g_object_get_data(G_OBJECT(widget), widget_name);
|
2009-04-05 21:07:40 +00:00
|
|
|
if (G_UNLIKELY(found_widget == NULL))
|
2008-12-18 21:21:53 +00:00
|
|
|
g_warning("Widget not found: %s", widget_name);
|
|
|
|
return found_widget;
|
2008-12-02 18:33:41 +00:00
|
|
|
}
|
2009-01-27 20:19:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Progress Bar */
|
|
|
|
static guint progress_bar_timer_id = (guint) -1;
|
|
|
|
|
|
|
|
|
|
|
|
static GtkWidget *progress_bar_create(void)
|
|
|
|
{
|
|
|
|
GtkWidget *bar = gtk_progress_bar_new();
|
|
|
|
|
|
|
|
/* Set the progressbar's height to 1 to fit it in the statusbar */
|
|
|
|
gtk_widget_set_size_request(bar, -1, 1);
|
|
|
|
gtk_box_pack_start (GTK_BOX(ui_widgets.statusbar), bar, FALSE, FALSE, 3);
|
|
|
|
|
|
|
|
return bar;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean progress_bar_pulse(gpointer data)
|
|
|
|
{
|
|
|
|
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(main_widgets.progressbar));
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts a constantly pulsing progressbar in the right corner of the statusbar
|
|
|
|
* (if the statusbar is visible). This is a convenience function which adds a timer to
|
|
|
|
* pulse the progressbar constantly until ui_progress_bar_stop() is called.
|
|
|
|
* You can use this function when you have time consuming asynchronous operation and want to
|
|
|
|
* display some activity in the GUI and when you don't know about detailed progress steps.
|
|
|
|
* The progressbar widget is hidden by default when it is not active. This function and
|
|
|
|
* ui_progress_bar_stop() will show and hide it automatically for you.
|
|
|
|
*
|
|
|
|
* You can also access the progressbar widget directly using @c geany->main_widgets->progressbar
|
|
|
|
* and use the GtkProgressBar API to set discrete fractions to display better progress information.
|
|
|
|
* In this case, you need to show and hide the widget yourself. You can find some example code
|
|
|
|
* in @c src/printing.c.
|
|
|
|
*
|
|
|
|
* @param text The text to be shown as the progress bar label or NULL to leave it empty.
|
2009-01-30 18:53:23 +00:00
|
|
|
*
|
|
|
|
* @since 0.16
|
|
|
|
**/
|
2009-01-27 20:19:43 +00:00
|
|
|
void ui_progress_bar_start(const gchar *text)
|
|
|
|
{
|
2009-04-15 22:47:33 +00:00
|
|
|
g_return_if_fail(progress_bar_timer_id == (guint) -1);
|
2009-01-27 20:19:43 +00:00
|
|
|
|
|
|
|
if (! interface_prefs.statusbar_visible)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(main_widgets.progressbar), text);
|
|
|
|
|
|
|
|
progress_bar_timer_id = g_timeout_add(200, progress_bar_pulse, NULL);
|
|
|
|
|
|
|
|
gtk_widget_show(GTK_WIDGET(main_widgets.progressbar));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-30 18:53:23 +00:00
|
|
|
/** Stops a running progress bar and hides the widget again.
|
|
|
|
*
|
|
|
|
* @since 0.16
|
|
|
|
**/
|
2009-01-27 20:19:43 +00:00
|
|
|
void ui_progress_bar_stop(void)
|
|
|
|
{
|
|
|
|
gtk_widget_hide(GTK_WIDGET(main_widgets.progressbar));
|
|
|
|
|
|
|
|
if (progress_bar_timer_id != (guint) -1)
|
|
|
|
{
|
|
|
|
g_source_remove(progress_bar_timer_id);
|
|
|
|
progress_bar_timer_id = (guint) -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-08 12:25:47 +00:00
|
|
|
|
|
|
|
static gint compare_menu_item_labels(gconstpointer a, gconstpointer b)
|
|
|
|
{
|
|
|
|
GtkMenuItem *item_a = GTK_MENU_ITEM(a);
|
|
|
|
GtkMenuItem *item_b = GTK_MENU_ITEM(b);
|
|
|
|
gchar *sa, *sb;
|
|
|
|
gint result;
|
|
|
|
|
|
|
|
sa = ui_menu_item_get_text(item_a);
|
|
|
|
sb = ui_menu_item_get_text(item_b);
|
|
|
|
result = utils_str_casecmp(sa, sb);
|
|
|
|
g_free(sa);
|
|
|
|
g_free(sb);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Currently @a menu should contain only GtkMenuItems with labels. */
|
|
|
|
void ui_menu_sort_by_label(GtkMenu *menu)
|
|
|
|
{
|
|
|
|
GList *list = gtk_container_get_children(GTK_CONTAINER(menu));
|
|
|
|
GList *node;
|
|
|
|
gint pos;
|
|
|
|
|
|
|
|
list = g_list_sort(list, compare_menu_item_labels);
|
|
|
|
pos = 0;
|
2009-06-12 15:32:35 +00:00
|
|
|
foreach_list(node, list)
|
2009-04-08 12:25:47 +00:00
|
|
|
{
|
2009-06-12 15:32:35 +00:00
|
|
|
gtk_menu_reorder_child(menu, node->data, pos);
|
2009-04-08 12:25:47 +00:00
|
|
|
pos++;
|
|
|
|
}
|
|
|
|
g_list_free(list);
|
|
|
|
}
|
|
|
|
|
2009-09-21 16:21:03 +00:00
|
|
|
|
|
|
|
/* return value is for macros */
|
|
|
|
GtkWidget *ui_label_set_markup(GtkLabel *label, const gchar *format, ...)
|
|
|
|
{
|
|
|
|
va_list a;
|
|
|
|
gchar *text;
|
|
|
|
|
|
|
|
va_start(a, format);
|
|
|
|
text = g_strdup_vprintf(format, a);
|
|
|
|
va_end(a);
|
|
|
|
|
|
|
|
gtk_label_set_text(label, text);
|
|
|
|
gtk_label_set_use_markup(label, TRUE);
|
|
|
|
g_free(text);
|
|
|
|
return GTK_WIDGET(label);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-05 21:13:47 +00:00
|
|
|
GtkWidget *ui_label_new_bold(const gchar *text)
|
|
|
|
{
|
|
|
|
GtkWidget *label;
|
|
|
|
gchar *label_text;
|
|
|
|
|
|
|
|
label_text = g_markup_escape_text(text, -1);
|
|
|
|
label = ui_label_set_markup(GTK_LABEL(gtk_label_new(NULL)), "<b>%s</b>", label_text);
|
|
|
|
g_free(label_text);
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-12 18:15:48 +00:00
|
|
|
/** Adds a list of document items to @a menu.
|
2009-10-13 17:14:25 +00:00
|
|
|
* @param menu Menu.
|
|
|
|
* @param active Which document to highlight, or @c NULL.
|
|
|
|
* @param callback is used for each menu item's @c "activate" signal and will be passed
|
|
|
|
* the corresponding document pointer as @c user_data.
|
2009-10-14 12:21:18 +00:00
|
|
|
* @warning You should check @c doc->is_valid in the callback.
|
|
|
|
* @since 0.19 */
|
2009-10-13 17:14:25 +00:00
|
|
|
void ui_menu_add_document_items(GtkMenu *menu, GeanyDocument *active, GCallback callback)
|
|
|
|
{
|
|
|
|
GtkWidget *menu_item, *menu_item_label;
|
|
|
|
const GdkColor *color;
|
|
|
|
GeanyDocument *doc;
|
|
|
|
guint i, len;
|
2010-08-05 21:13:47 +00:00
|
|
|
gchar *base_name, *label;
|
2009-10-13 17:14:25 +00:00
|
|
|
|
|
|
|
len = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook));
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
doc = document_get_from_page(i);
|
|
|
|
if (! DOC_VALID(doc))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
base_name = g_path_get_basename(DOC_FILENAME(doc));
|
|
|
|
menu_item = gtk_menu_item_new_with_label(base_name);
|
|
|
|
gtk_widget_show(menu_item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), menu_item);
|
|
|
|
g_signal_connect(menu_item, "activate", callback, doc);
|
|
|
|
|
|
|
|
color = document_get_status_color(doc);
|
|
|
|
menu_item_label = gtk_bin_get_child(GTK_BIN(menu_item));
|
|
|
|
gtk_widget_modify_fg(menu_item_label, GTK_STATE_NORMAL, color);
|
|
|
|
gtk_widget_modify_fg(menu_item_label, GTK_STATE_ACTIVE, color);
|
|
|
|
|
|
|
|
if (doc == active)
|
2010-08-05 21:13:47 +00:00
|
|
|
{
|
|
|
|
label = g_markup_escape_text(base_name, -1);
|
|
|
|
ui_label_set_markup(GTK_LABEL(menu_item_label), "<b>%s</b>", label);
|
|
|
|
g_free(label);
|
|
|
|
}
|
2009-10-13 17:14:25 +00:00
|
|
|
|
|
|
|
g_free(base_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-12 18:15:48 +00:00
|
|
|
/** Checks whether the passed @a keyval is the Enter or Return key.
|
2010-03-07 19:33:15 +00:00
|
|
|
* There are three different Enter/Return key values
|
|
|
|
* (@c GDK_Return, @c GDK_ISO_Enter, @c GDK_KP_Enter).
|
|
|
|
* This is just a convenience function.
|
|
|
|
* @param keyval A keyval.
|
|
|
|
* @return @c TRUE if @a keyval is the one of the Enter/Return key values, otherwise @c FALSE.
|
|
|
|
* @since 0.19 */
|
|
|
|
gboolean ui_is_keyval_enter_or_return(guint keyval)
|
|
|
|
{
|
|
|
|
return (keyval == GDK_Return || keyval == GDK_ISO_Enter|| keyval == GDK_KP_Enter);
|
|
|
|
}
|
2010-04-11 21:56:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
/** Reads an integer from the GTK default settings registry
|
|
|
|
* (see http://library.gnome.org/devel/gtk/stable/GtkSettings.html).
|
|
|
|
* @param property_name The property to read.
|
|
|
|
* @param default_value The default value in case the value could not be read.
|
|
|
|
* @return The value for the property if it exists, otherwise the @a default_value.
|
|
|
|
* @since 0.19 */
|
|
|
|
gint ui_get_gtk_settings_integer(const gchar *property_name, gint default_value)
|
|
|
|
{
|
|
|
|
if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(
|
|
|
|
gtk_settings_get_default())), property_name))
|
|
|
|
{
|
|
|
|
gint value;
|
|
|
|
g_object_get(G_OBJECT(gtk_settings_get_default()), property_name, &value, NULL);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return default_value;
|
|
|
|
}
|
2010-05-09 15:48:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
void ui_editable_insert_text_callback(GtkEditable *editable, gchar *new_text,
|
|
|
|
gint new_text_len, gint *position, gpointer data)
|
|
|
|
{
|
|
|
|
gboolean stop_signal = FALSE;
|
|
|
|
const gchar c = *new_text;
|
|
|
|
|
|
|
|
/* allow inserting '+' and '-' as the first character */
|
|
|
|
if (position != NULL && *position == 0)
|
|
|
|
{
|
|
|
|
if (c != '+' && c != '-' && ! isdigit(c))
|
|
|
|
stop_signal = TRUE;
|
|
|
|
}
|
|
|
|
/* don't insert any text when it is not a digit */
|
|
|
|
else if (! isdigit(c))
|
|
|
|
stop_signal = TRUE;
|
|
|
|
|
|
|
|
if (stop_signal)
|
|
|
|
g_signal_stop_emission_by_name(editable, "insert-text");
|
|
|
|
}
|
|
|
|
|