medit/moo/mooedit/mooeditor.c

360 lines
9.9 KiB
C

/*
* mooedit/mooeditor.c
*
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
*
* 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.
*
* See COPYING file that comes with this distribution.
*/
#define MOOEDIT_COMPILATION
#include "mooedit/mooeditor.h"
#include "mooedit/mooeditdialogs.h"
#include "mooui/moouiobject.h"
#include "mooutils/moocompat.h"
#include "mooutils/moomarshals.h"
#include "mooutils/moowin.h"
struct _MooEditorPrivate {
GSList *windows;
char *app_name;
MooEditLangMgr *lang_mgr;
MooUIXML *ui_xml;
};
static void moo_editor_finalize (GObject *object);
static void add_window (MooEditor *editor,
MooEditWindow *window);
static void remove_window (MooEditor *editor,
MooEditWindow *window);
static gboolean contains_window (MooEditor *editor,
MooEditWindow *window);
static MooEditWindow *get_top_window (MooEditor *editor);
static gboolean window_closed (MooEditor *editor,
MooEditWindow *window);
enum {
NEW_WINDOW,
NEW_DOCUMENT,
ALL_WINDOWS_CLOSED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
/* MOO_TYPE_EDITOR */
G_DEFINE_TYPE (MooEditor, moo_editor, G_TYPE_OBJECT)
static void moo_editor_class_init (MooEditorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = moo_editor_finalize;
klass->new_window = NULL;
klass->new_document = NULL;
klass->all_windows_closed = NULL;
signals[NEW_WINDOW] =
g_signal_new ("new-window",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MooEditorClass, new_window),
NULL, NULL,
_moo_marshal_VOID__OBJECT,
/* G_TYPE_OBJECT to not put MOO_TYPE_WHATEVER into marshals.list */
G_TYPE_NONE, 1, G_TYPE_OBJECT);
signals[NEW_DOCUMENT] =
g_signal_new ("new-document",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MooEditorClass, new_window),
NULL, NULL,
_moo_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_OBJECT);
signals[ALL_WINDOWS_CLOSED] =
g_signal_new ("all-windows-closed",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MooEditorClass, all_windows_closed),
NULL, NULL,
_moo_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void moo_editor_init (MooEditor *editor)
{
editor->priv = g_new0 (MooEditorPrivate, 1);
}
static void moo_editor_finalize (GObject *object)
{
MooEditor *editor = MOO_EDITOR (object);
g_free (editor->priv->app_name);
if (editor->priv->lang_mgr)
g_object_unref (editor->priv->lang_mgr);
if (editor->priv->ui_xml)
g_object_unref (editor->priv->ui_xml);
g_free (editor->priv);
G_OBJECT_CLASS (moo_editor_parent_class)->finalize (object);
}
MooEditor *moo_editor_new (void)
{
return MOO_EDITOR (g_object_new (MOO_TYPE_EDITOR, NULL));
}
MooEditWindow *moo_editor_new_window (MooEditor *editor)
{
MooEditWindow *window;
g_return_val_if_fail (MOO_IS_EDITOR (editor), NULL);
window = MOO_EDIT_WINDOW (_moo_edit_window_new (editor));
g_return_val_if_fail (window != NULL, NULL);
add_window (editor, window);
gtk_widget_show (GTK_WIDGET (window));
return window;
}
static void add_window (MooEditor *editor,
MooEditWindow *window)
{
MooUIXML *ui_xml;
g_return_if_fail (!contains_window (editor, window));
g_return_if_fail (window != NULL);
/* it may not be destroyed until all windows have been closed*/
g_object_ref (editor);
editor->priv->windows =
g_slist_prepend (editor->priv->windows, window);
_moo_edit_window_set_app_name (MOO_EDIT_WINDOW (window),
editor->priv->app_name);
ui_xml = moo_editor_get_ui_xml (editor);
moo_ui_object_set_ui_xml (MOO_UI_OBJECT (window), ui_xml);
g_signal_connect_data (window, "close",
G_CALLBACK (window_closed), editor,
NULL,
G_CONNECT_AFTER | G_CONNECT_SWAPPED);
}
static void remove_window (MooEditor *editor,
MooEditWindow *window)
{
g_return_if_fail (contains_window (editor, window));
g_return_if_fail (window != NULL);
g_object_unref (editor);
editor->priv->windows = g_slist_remove (editor->priv->windows, window);
if (!editor->priv->windows)
g_signal_emit (editor, signals[ALL_WINDOWS_CLOSED], 0, NULL);
}
static MooEditWindow *get_top_window (MooEditor *editor)
{
if (editor->priv->windows)
return MOO_EDIT_WINDOW (moo_get_top_window (editor->priv->windows));
else
return NULL;
}
static gboolean contains_window (MooEditor *editor,
MooEditWindow *window)
{
return g_slist_find (editor->priv->windows, window) != NULL;
}
static gboolean window_closed (MooEditor *editor,
MooEditWindow *window)
{
g_return_val_if_fail (contains_window (editor, window), TRUE);
remove_window (editor, window);
return FALSE;
}
gboolean moo_editor_open (MooEditor *editor,
MooEditWindow *window,
GtkWidget *parent,
const char *filename,
const char *encoding)
{
MooEditFileInfo *info = NULL;
gboolean result;
g_return_val_if_fail (MOO_IS_EDITOR (editor), FALSE);
g_return_val_if_fail (window == NULL || MOO_IS_EDIT_WINDOW (window), FALSE);
if (!parent && window)
parent = GTK_WIDGET (window);
if (!filename)
{
info = moo_edit_open_dialog (parent);
if (!info)
{
return FALSE;
}
else
{
filename = info->filename;
encoding = info->encoding;
}
}
if (!window)
window = get_top_window (editor);
if (!window)
window = moo_editor_new_window (editor);
if (!window)
{
moo_edit_file_info_free (info);
g_return_val_if_reached (FALSE);
}
gtk_window_present (GTK_WINDOW (window));
result = moo_edit_window_open (window, filename, encoding);
moo_edit_file_info_free (info);
return result;
}
MooEdit *moo_editor_get_active_doc (MooEditor *editor)
{
MooEditWindow *window;
g_return_val_if_fail (MOO_IS_EDITOR (editor), NULL);
window = get_top_window (editor);
if (window)
return moo_edit_window_get_active_doc (window);
else
return NULL;
}
MooEditWindow *moo_editor_get_active_window (MooEditor *editor)
{
g_return_val_if_fail (MOO_IS_EDITOR (editor), NULL);
return get_top_window (editor);
}
gboolean moo_editor_close_all (MooEditor *editor)
{
GSList *list, *l;
MooWindow *win;
g_return_val_if_fail (MOO_IS_EDITOR (editor), FALSE);
list = g_slist_copy (editor->priv->windows);
for (l = list; l != NULL; l = l->next)
{
win = MOO_WINDOW (l->data);
if (!(GTK_IN_DESTRUCTION & GTK_OBJECT_FLAGS (win)) &&
!moo_window_close (win))
{
g_slist_free (list);
return FALSE;
}
}
g_slist_free (list);
return TRUE;
}
void moo_editor_set_app_name (MooEditor *editor,
const char *name)
{
GSList *l;
g_return_if_fail (MOO_IS_EDITOR (editor));
g_free (editor->priv->app_name);
editor->priv->app_name = g_strdup (name);
for (l = editor->priv->windows; l != NULL; l = l->next)
_moo_edit_window_set_app_name (MOO_EDIT_WINDOW (l->data),
name);
}
MooEditLangMgr *moo_editor_get_lang_mgr (MooEditor *editor)
{
g_return_val_if_fail (MOO_IS_EDITOR (editor), NULL);
if (!editor->priv->lang_mgr)
editor->priv->lang_mgr = moo_edit_lang_mgr_new ();
return editor->priv->lang_mgr;
}
MooUIXML *moo_editor_get_ui_xml (MooEditor *editor)
{
g_return_val_if_fail (MOO_IS_EDITOR (editor), NULL);
if (!editor->priv->ui_xml)
editor->priv->ui_xml = moo_ui_xml_new ();
return editor->priv->ui_xml;
}
void moo_editor_set_ui_xml (MooEditor *editor,
MooUIXML *xml)
{
GSList *l;
g_return_if_fail (MOO_IS_EDITOR (editor));
if (editor->priv->ui_xml == xml)
return;
if (editor->priv->ui_xml)
g_object_unref (editor->priv->ui_xml);
editor->priv->ui_xml = xml;
if (xml)
g_object_ref (editor->priv->ui_xml);
for (l = editor->priv->windows; l != NULL; l = l->next)
moo_ui_object_set_ui_xml (MOO_UI_OBJECT (l->data),
editor->priv->ui_xml);
}