/*
* This program is a bonobo container whith an emacs like user interface
* (based on sample-container from Nat Friedman (nat@nat.org))
*
* Author:
* Dietmar Maurer (dietmar@maurer-it.com)
*
* Copyright 1999 Maurer IT Systemlösungen (http://www.maurer-it.com)
*/
#include <config.h>
#include "gshell.h"
#include "inout.h"
#include "ui.h"
#include "properties.h"
#include "controls.h"
#include <liboaf/liboaf.h>
Application app;
static void
verb_HelpGNOME_cb (BonoboUIComponent *component, Frame *frame, const char *cname)
{
gchar *p;
p = gnome_help_file_path ("help-browser", "default-page.html");
if (p)
gnome_help_goto (NULL, p);
}
static void
verb_HelpAbout_cb (BonoboUIComponent *component, Frame *frame, const char *cname)
{
static GtkWidget *about;
const gchar *authors[] = {
"Dietmar Maurer",
NULL
};
about = gnome_about_new
( "Gnome Shell", VERSION,
"Copyright (C) 1999 Maurer IT Systemlösungen"
" ",
authors,
_("This program is part of the GNOME project. "
"Gnome Shell comes with ABSOLUTELY NO "
"WARRANTY. This is free software, and you are "
"welcome to redistribute it under the conditions "
"of the GNU General Public License. "
"Please report bugs to dietmar@maurer-it.com"),
NULL);
gtk_widget_show (about);
}
static void
verb_SettingsPreferences_cb (BonoboUIComponent *component,
Frame *frame, const char *cname)
{
show_property_dialog (
BONOBO_CONTROL_FRAME (frame->active_view_frame));
}
Frame *
get_active_frame (GtkWidget *widget)
{
GtkWidget *top;
GList *l;
Frame *frame;
g_return_val_if_fail (widget != NULL, NULL);
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
top = gtk_widget_get_toplevel(widget);
for (l = app.frame_list;l;l = l->next) {
frame = (Frame *)l->data;
if (GTK_WIDGET (frame->win) == top)
return frame;
}
return NULL;
}
static void
container_system_exception_cb (BonoboObject *container_object,
CORBA_Object cobject,
CORBA_Environment *ev, gpointer data)
{
gnome_warning_dialog (_("fatal CORBA exception! Shutting down..."));
bonobo_object_unref (BONOBO_OBJECT (app.container));
gtk_main_quit ();
}
static void
client_site_system_exception_cb (BonoboObject *client, CORBA_Object cobject,
CORBA_Environment *ev, gpointer data)
{
/* Buffer *buffer = (Buffer *) data; */
g_warning ("component shutdown not implemented");
/* bonobo_object_unref (BONOBO_OBJECT (buffer->client_site)); */
}
static void
view_system_exception_cb (BonoboViewFrame *view_frame, CORBA_Object cobject,
CORBA_Environment *ev, gpointer data)
{
g_warning ("view frame system exception not implemented");
bonobo_object_unref (BONOBO_OBJECT (view_frame));
}
static void
user_activate_request_cb (BonoboViewFrame *view_frame, Frame *frame)
{
if (frame->active_view_frame == view_frame)
return;
if (frame->active_view_frame != NULL) {
bonobo_view_frame_view_deactivate (frame->active_view_frame);
if (frame->active_view_frame != NULL)
bonobo_view_frame_set_covered
(frame->active_view_frame, TRUE);
frame->active_view_frame = NULL;
}
bonobo_view_frame_view_activate (view_frame);
}
static void
view_activated_cb (BonoboViewFrame *view_frame, gboolean activated,
Frame *frame)
{
GtkWidget *w;
if (activated) {
if (frame->active_view_frame != NULL) {
g_warning ("View requested to be activated "
"but there is already "
"an active View!\n");
return;
}
bonobo_view_frame_set_covered (view_frame, FALSE);
frame->active_view_frame = view_frame;
w = bonobo_view_frame_get_wrapper (view_frame);
/* gtk_container_focus (GTK_CONTAINER(w), GTK_DIR_UP); */
gtk_widget_grab_focus(w);
frame_set_sensitive (frame, TRUE);
} else {
bonobo_view_frame_set_covered (view_frame, TRUE);
if (view_frame == frame->active_view_frame)
frame->active_view_frame = NULL;
}
}
static void
zoom_level_changed_cb (GtkWidget *widget, float zoom_level, Frame *frame)
{
gchar *message;
message = g_strdup_printf (_("New zoom level is %.3g."), zoom_level);
bonobo_ui_component_set_status (frame->component, message, NULL);
g_free (message);
}
static void
buffer_create_zoomable_frame (Buffer *buffer, Frame *frame, BonoboViewFrame *view_frame)
{
Bonobo_Control control;
Bonobo_Zoomable zoomable;
control = bonobo_control_frame_get_control (BONOBO_CONTROL_FRAME (view_frame));
zoomable = Bonobo_Unknown_queryInterface (control, "IDL:Bonobo/Zoomable:1.0", NULL);
if (zoomable != CORBA_OBJECT_NIL) {
g_message ("Zooming interface found");
buffer->zoomable_frame = bonobo_zoomable_frame_new ();
bonobo_zoomable_frame_bind_to_zoomable (buffer->zoomable_frame, zoomable);
gtk_signal_connect (GTK_OBJECT (buffer->zoomable_frame), "zoom_level_changed",
GTK_SIGNAL_FUNC (zoom_level_changed_cb), frame);
frame_set_zoomable (frame, TRUE);
} else
frame_set_zoomable (frame, FALSE);
}
void
buffer_add_view (Buffer *buffer, Frame *frame, gint pos)
{
BonoboViewFrame *view_frame;
GtkWidget *view_widget;
GtkWidget *box,*l;
view_frame = bonobo_client_site_new_view_full (
buffer->client_site,
bonobo_object_corba_objref (BONOBO_OBJECT (frame->container)),
FALSE, TRUE);
if (!view_frame) {
g_warning ("create view failed");
return;
}
gtk_object_set_data (GTK_OBJECT(view_frame), "gshell:buffer", buffer);
frame->view_list = g_list_append (frame->view_list, view_frame);
gtk_signal_connect (GTK_OBJECT (view_frame), "system_exception",
view_system_exception_cb, buffer);
gtk_signal_connect (GTK_OBJECT (view_frame), "user_activate",
GTK_SIGNAL_FUNC (user_activate_request_cb), frame);
gtk_signal_connect (GTK_OBJECT (view_frame), "activated",
GTK_SIGNAL_FUNC (view_activated_cb), frame);
view_widget = bonobo_view_frame_get_wrapper (view_frame);
box = gtk_vbox_new (FALSE,0);
gtk_object_set_data (GTK_OBJECT(box), "gshell:view_frame", view_frame);
l = gtk_label_new (buffer->name);
gtk_box_pack_start (GTK_BOX (box), l, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), view_widget, TRUE, TRUE, 0);
gtk_box_pack_end (GTK_BOX (frame->vbox), box, TRUE, TRUE, 0);
if (pos>=0) gtk_box_reorder_child (GTK_BOX (frame->vbox), box, pos);
gtk_widget_show_all (box);
user_activate_request_cb (view_frame, frame);
buffer_create_zoomable_frame (buffer, frame, view_frame);
}
static Buffer *
real_buffer_create (BonoboObjectClient *server)
{
Buffer *buffer;
BonoboClientSite *client_site;
client_site = bonobo_client_site_new (app.container);
if (!bonobo_client_site_bind_embeddable (client_site, server)) {
bonobo_object_unref (BONOBO_OBJECT (server));
bonobo_object_unref (BONOBO_OBJECT (client_site));
g_warning("Bind component failed");
return NULL;
}
bonobo_object_client_unref (server, NULL);
buffer = g_new0 (Buffer, 1);
buffer->client_site = client_site;
buffer->server = server;
app.buffer_list = g_list_append (app.buffer_list, buffer);
gtk_signal_connect (GTK_OBJECT (client_site), "system_exception",
client_site_system_exception_cb, buffer);
return buffer;
}
static Buffer *
real_buffer_create_embeddable (const char *component_oaf_iid)
{
BonoboObjectClient *server;
server = bonobo_object_activate (component_oaf_iid, 0);
if (!server) {
g_warning ("Launching component failed");
return NULL;
}
return real_buffer_create (server);
}
static Buffer *
real_buffer_create_control (const char *component_oaf_iid)
{
BonoboObjectClient *server;
server = gshell_control_wrapper (component_oaf_iid);
if (!server) {
g_warning ("Launching component failed");
return NULL;
}
return real_buffer_create (server);
}
Buffer *
buffer_create (const char *component_oaf_iid)
{
Buffer *retval;
OAF_ServerInfoList *servers;
CORBA_Environment ev;
gchar *query;
CORBA_exception_init (&ev);
query = g_strdup_printf ("(iid == '%s') AND repo_ids.has('IDL:Bonobo/Embeddable:1.0')",
component_oaf_iid);
servers = oaf_query (query, NULL, &ev);
g_free (query);
CORBA_exception_free (&ev);
if ((servers != NULL) && (servers->_length > 0))
retval = real_buffer_create_embeddable (component_oaf_iid);
else
retval = real_buffer_create_control (component_oaf_iid);
CORBA_free (servers);
return retval;
}
Buffer *
buffer_create_for_control (const char *component_oaf_iid)
{
return real_buffer_create_control (component_oaf_iid);
}
static GtkWidget *
find_view_frame_pos (Frame *frame, BonoboViewFrame *view_frame, gint *pos)
{
GList *l;
gint i = 0;
GtkObject *o = NULL;
l = GTK_BOX(frame->vbox)->children;
while (l && (o = GTK_OBJECT (((GtkBoxChild *)l->data)->widget)) &&
(gtk_object_get_data (o, "gshell:view_frame") != view_frame)) {
i++; l = l->next;
}
if (pos) *pos = i;
if (o)
return GTK_WIDGET (o);
return NULL;
}
gint
view_remove (Frame *frame, BonoboViewFrame *view_frame)
{
GtkWidget *w,*b;
gint pos;
w = bonobo_view_frame_get_wrapper (view_frame);
frame->view_list = g_list_remove (frame->view_list, view_frame);
if (frame->active_view_frame == view_frame)
frame->active_view_frame = NULL;
b = find_view_frame_pos (frame, view_frame, &pos);
gtk_widget_destroy (w);
bonobo_object_unref (BONOBO_OBJECT (view_frame));
if (b)
gtk_widget_destroy (b);
return pos;
}
static void
frame_close_cb (GtkWidget *widget, Frame *frame)
{
BonoboViewFrame *view_frame;
GList *v;
while ((v = frame->view_list)) {
view_frame = (BonoboViewFrame *)v->data;
view_remove (frame, view_frame);
}
app.frame_list = g_list_remove (app.frame_list, frame);
gtk_widget_destroy (GTK_WIDGET (frame->win));
if (!g_list_length(app.frame_list))
gtk_main_quit ();
}
static void
verb_FileExit_cb (BonoboUIComponent *component, Frame *frame, const char *cname)
{
bonobo_object_unref (BONOBO_OBJECT (app.container));
gtk_main_quit ();
}
static void
verb_WindowClose_cb (BonoboUIComponent *component, Frame *frame, const char *cname)
{
frame_close_cb (NULL, frame);
}
static Frame *
frame_create ()
{
Frame *frame;
GtkWidget *statusbar;
frame = g_new0 (Frame, 1);
frame->win = BONOBO_WINDOW (bonobo_window_new ("gshell", "Gnome Shell"));
gtk_window_set_default_size (GTK_WINDOW (frame->win), 640, 400);
gtk_window_set_policy (GTK_WINDOW (frame->win), TRUE, TRUE, FALSE);
gtk_signal_connect (GTK_OBJECT (frame->win), "delete_event",
GTK_SIGNAL_FUNC (frame_close_cb), frame);
statusbar = gtk_statusbar_new ();
frame->vbox = gtk_vbox_new (FALSE, 0);
bonobo_window_set_contents (frame->win, frame->vbox);
frame->container = bonobo_ui_container_new ();
bonobo_ui_container_set_win (frame->container, frame->win);
frame_create_ui (frame);
frame_set_sensitive (frame, FALSE);
frame_set_zoomable (frame, FALSE);
gtk_widget_show_all (GTK_WIDGET (frame->win));
app.frame_list = g_list_append (app.frame_list, frame);
return frame;
}
BonoboViewFrame *
get_active_view_frame (Frame *frame)
{
GtkWidget *w = NULL;
BonoboViewFrame *view_frame = NULL;
if (!(w = GTK_CONTAINER(frame->vbox)->focus_child)) {
if (g_list_length(frame->view_list)) {
view_frame = BONOBO_VIEW_FRAME(frame->view_list->data);
return view_frame;
}
}
if (w)
return gtk_object_get_data (GTK_OBJECT (w),
"gshell:view_frame");
return NULL;
}
static void
verb_WindowCreateNew_cb (BonoboUIComponent *component, Frame *frame, const char *cname)
{
BonoboViewFrame *view_frame;
Buffer *buffer = NULL;
if ((view_frame = get_active_view_frame (frame))) {
buffer = gtk_object_get_data(GTK_OBJECT(view_frame),
"gshell:buffer");
}
frame = frame_create ();
if (buffer)
buffer_add_view (buffer, frame, -1);
update_buffer_menu ();
}
static void
verb_WindowSplit_cb (BonoboUIComponent *component, Frame *frame, const char *cname)
{
BonoboViewFrame *view_frame;
Buffer *buffer = NULL;
gint pos;
if ((view_frame = get_active_view_frame (frame))) {
find_view_frame_pos (frame, view_frame, &pos);
buffer = gtk_object_get_data(GTK_OBJECT(view_frame),
"gshell:buffer");
if (buffer)
buffer_add_view (buffer, frame, pos);
}
}
static void
verb_WindowOne_cb (BonoboUIComponent *component, Frame *frame, const char *cname)
{
BonoboViewFrame *view_frame, *vf;
GList *v;
if ((view_frame = get_active_view_frame (frame))) {
for (v = frame->view_list; v;) {
vf = (BonoboViewFrame *) v->data;
v = v->next;
if (view_frame != vf)
view_remove (frame, vf);
}
}
}
static void
verb_FileKill_cb (BonoboUIComponent *component, Frame *frame, const char *cname)
{
Buffer *buffer=NULL;
BonoboViewFrame *view_frame;
GList *f,*v,*b;
gchar *path;
if ((view_frame = get_active_view_frame (frame))) {
buffer = gtk_object_get_data(GTK_OBJECT(view_frame),
"gshell:buffer");
} else
return;
if (!buffer)
return;
app.buffer_list = g_list_remove (app.buffer_list, buffer);
for (f = app.frame_list; f; f = f->next) {
frame = (Frame *) f->data;
for (v = frame->view_list; v;) {
view_frame = (BonoboViewFrame *) v->data;
v = v->next;
if (buffer == gtk_object_get_data (
GTK_OBJECT(view_frame), "gshell:buffer")) {
view_remove (frame, view_frame);
if (!g_list_length (GTK_BOX (frame->vbox)->children)) {
if ((b = g_list_last (app.buffer_list)))
buffer_add_view ((Buffer *) b->data,
frame, -1);
else
frame_set_sensitive (frame, FALSE);
}
}
}
}
bonobo_object_unref (BONOBO_OBJECT (buffer->client_site));
path = g_strdup_printf ("/commands/%s", buffer->verb);
bonobo_ui_component_rm (frame->component, path, NULL);
g_free (path);
update_buffer_menu ();
if (buffer->name) {
g_free (buffer->name);
buffer->name = NULL;
}
g_free (buffer);
}
void
open_files (Frame *frame, int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
file_open (frame, argv [i]);
}
static void
zoom_custom_cb (gchar *string, gpointer user_data)
{
BonoboViewFrame *view_frame;
Frame *frame = user_data;
gchar *end = NULL;
double zoom_level;
if (string == NULL)
return;
zoom_level = g_strtod (string, &end);
if (end && *end != '\x00') {
g_warning ("Invalid zoom level `%s'", string);
return;
}
view_frame = get_active_view_frame (frame);
if (!view_frame)
return;
bonobo_view_frame_set_zoom_factor (view_frame, zoom_level);
}
static void
zoom_custom (Frame *frame)
{
GtkWidget *dialog;
dialog = gnome_request_dialog (FALSE, _("Set zoom level:"), NULL, 10,
zoom_custom_cb, frame, GTK_WINDOW (frame->win));
gnome_dialog_run (GNOME_DIALOG (dialog));
}
static void
verb_Zoom_cb (BonoboUIComponent *component, Frame *frame, const char *cname)
{
BonoboViewFrame *view_frame;
Buffer *buffer = NULL;
view_frame = get_active_view_frame (frame);
if (!view_frame)
return;
buffer = gtk_object_get_data (GTK_OBJECT (view_frame), "gshell:buffer");
if (!buffer)
return;
if (!buffer->zoomable_frame)
return;
if (!strcmp (cname, "ZoomIn"))
bonobo_zoomable_frame_zoom_in (buffer->zoomable_frame);
else if (!strcmp (cname, "ZoomOut"))
bonobo_zoomable_frame_zoom_out (buffer->zoomable_frame);
else if (!strcmp (cname, "ZoomToFit"))
bonobo_zoomable_frame_zoom_to_fit (buffer->zoomable_frame);
else if (!strcmp (cname, "ZoomToDefault"))
bonobo_zoomable_frame_zoom_to_default (buffer->zoomable_frame);
else
zoom_custom (frame);
}
int
main (int argc, char **argv)
{
CORBA_Environment ev;
CORBA_ORB orb;
Frame *frame;
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
textdomain (PACKAGE);
CORBA_exception_init (&ev);
gnome_init_with_popt_table ("gshell", "1.0",
argc, argv,
oaf_popt_options, 0, NULL);
CORBA_exception_free (&ev);
orb = oaf_init (argc, argv);
if (bonobo_init (orb, NULL, NULL) == FALSE)
g_error (_("Could not initialize Bonobo!"));
app.container = bonobo_item_container_new ();
gtk_signal_connect (GTK_OBJECT (app.container), "system_exception",
container_system_exception_cb, NULL);
frame = frame_create ();
bonobo_activate ();
open_files (frame, argc, argv);
bonobo_main ();
return 0;
}
BonoboUIVerb gshell_verbs[] = {
BONOBO_UI_UNSAFE_VERB ("FileKill", verb_FileKill_cb),
BONOBO_UI_UNSAFE_VERB ("FileExit", verb_FileExit_cb),
BONOBO_UI_UNSAFE_VERB ("SettingsPreferences", verb_SettingsPreferences_cb),
BONOBO_UI_UNSAFE_VERB ("WindowCreateNew", verb_WindowCreateNew_cb),
BONOBO_UI_UNSAFE_VERB ("WindowClose", verb_WindowClose_cb),
BONOBO_UI_UNSAFE_VERB ("WindowSplit", verb_WindowSplit_cb),
BONOBO_UI_UNSAFE_VERB ("WindowOne", verb_WindowOne_cb),
BONOBO_UI_UNSAFE_VERB ("ZoomIn", verb_Zoom_cb),
BONOBO_UI_UNSAFE_VERB ("ZoomOut", verb_Zoom_cb),
BONOBO_UI_UNSAFE_VERB ("ZoomToFit", verb_Zoom_cb),
BONOBO_UI_UNSAFE_VERB ("ZoomToDefault", verb_Zoom_cb),
BONOBO_UI_UNSAFE_VERB ("WindowZoom", verb_Zoom_cb),
BONOBO_UI_UNSAFE_VERB ("HelpGNOME", verb_HelpGNOME_cb),
BONOBO_UI_UNSAFE_VERB ("HelpAbout", verb_HelpAbout_cb),
BONOBO_UI_VERB_END
};
syntax highlighted by Code2HTML, v. 0.9.1