/* Screem: screem-view.c * * The base view widget * * Copyright (C) 2002 David A Knight * * 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 * * For contact information with the author of this source code please see * the AUTHORS file. If there is no AUTHORS file present then check the * about box under the help menu for a contact address */ #include #include "screem-window.h" #include "screem-site.h" #include "screem-page.h" #include "screem-view.h" enum { PROP_0, PROP_WINDOW, PROP_SITE, PROP_PAGE, PROP_ONLINE, PROP_UIMANAGER, PROP_ACTIONS, PROP_APP }; struct ScreemViewPrivate { ScreemWindow *window; ScreemPage *page; gboolean online; }; /* slight GCCism here with args */ #define SCREEM_CALL_IFACE( view, func, args... ) \ if( view->func != NULL ) \ view->func( view, ## args ) #define SET_ACTION( name, func ) \ action = gtk_action_group_get_action( group, name );\ if( action ) { \ gboolean active;\ active = ( page != NULL ) && ( view->func != NULL );\ gtk_action_set_sensitive( action, active );\ } /* base implementation */ void screem_view_display( ScreemView *view ) { GtkActionGroup *group; GtkAction *action; ScreemPage *page; g_return_if_fail( SCREEM_IS_VIEW( view ) ); SCREEM_CALL_IFACE( view, display ); /* if this view is visible we need to toggle * action sensitivity based on what the * view can do */ g_object_get( G_OBJECT( view ), "actions", &group, "page", &page, NULL ); if( group ) { if( GTK_WIDGET_VISIBLE( view ) ) { SET_ACTION( "Print", print ); SET_ACTION( "PrintPreview", print ); SET_ACTION( "Undo", undo ); SET_ACTION( "Redo", redo ); SET_ACTION( "Cut", cut ); SET_ACTION( "Copy", copy ); SET_ACTION( "Paste", paste ); SET_ACTION( "PasteEncoded", paste_encoded ); SET_ACTION( "PasteText", paste_unformatted ); SET_ACTION( "Clear", clear_selection ); SET_ACTION( "SelectAll", select_region ); SET_ACTION( "SelectContext", select_region ); SET_ACTION( "SelectContent", select_region ); } g_object_unref( group ); if( page ) { g_object_unref( page ); } } } void screem_view_print( ScreemView *view, gboolean preview ) { SCREEM_CALL_IFACE( view, print, preview ); } void screem_view_undo( ScreemView *view ) { SCREEM_CALL_IFACE( view, undo ); } void screem_view_redo( ScreemView *view ) { SCREEM_CALL_IFACE( view, redo ); } void screem_view_show_message( ScreemView *view, const gchar *msg ) { ScreemView *dview; ScreemViewPrivate *priv; dview = SCREEM_VIEW( view ); priv = dview->priv; if( priv->window ) { screem_window_show_message( priv->window, msg, FALSE ); } } void screem_view_show_error( ScreemView *view, const gchar *msg ) { ScreemView *dview; ScreemViewPrivate *priv; dview = SCREEM_VIEW( view ); priv = dview->priv; if( priv->window ) { screem_window_show_error( priv->window, msg, FALSE ); } } /* clipboard */ void screem_view_cut( ScreemView *view ) { SCREEM_CALL_IFACE( view, cut ); } void screem_view_copy( ScreemView *view ) { SCREEM_CALL_IFACE( view, copy ); } void screem_view_paste( ScreemView *view ) { SCREEM_CALL_IFACE( view, paste ); } void screem_view_paste_unformatted( ScreemView *view ) { SCREEM_CALL_IFACE( view, paste_unformatted ); } void screem_view_paste_encoded( ScreemView *view ) { SCREEM_CALL_IFACE( view, paste_encoded ); } void screem_view_clear_selection( ScreemView *view ) { SCREEM_CALL_IFACE( view, clear_selection ); } gboolean screem_view_has_selection( ScreemView *view, guint *start, guint *end ) { gboolean ret; ret = FALSE; if( view->has_selection != NULL ) { ret = view->has_selection( view, start, end ); } return ret; } void screem_view_select_region( ScreemView *view, guint start, guint end ) { SCREEM_CALL_IFACE( view, select_region, start, end ); } /* text insertion / deletion */ void screem_view_insert( ScreemView *view, gint pos, const gchar *text ) { SCREEM_CALL_IFACE( view, insert, pos, text ); } void screem_view_insert_markup( ScreemView *view, const gchar *open_element, const gchar *close_element ) { SCREEM_CALL_IFACE( view, insert_markup, open_element, close_element ); } void screem_view_insert_file( ScreemView *view, const gchar *filename ) { SCREEM_CALL_IFACE( view, insert_file, filename ); } void screem_view_insert_attribute( ScreemView *view, const gchar *attribute ) { SCREEM_CALL_IFACE( view, insert_attribute, attribute ); } void screem_view_delete_forward( ScreemView *view, guint pos, guint len ) { SCREEM_CALL_IFACE( view, delete_forward, pos, len ); } /* position / text functions */ gchar* screem_view_get_text( ScreemView *view, guint from, guint len ) { gchar *ret; ret = NULL; if( view->get_text != NULL ) { ret = view->get_text( view, from, len ); } return ret; } void screem_view_set_pos( ScreemView *view, guint pos ) { SCREEM_CALL_IFACE( view, set_pos, pos ); } guint screem_view_get_pos( ScreemView *view ) { guint ret; ret = 0; if( view->get_pos != NULL ) { ret = view->get_pos( view ); } return ret; } /* G Object stuff */ G_DEFINE_TYPE( ScreemView, screem_view, GTK_TYPE_BIN ) static void screem_view_finalize( GObject *view ); static void screem_view_set_prop( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec ); static void screem_view_get_prop( GObject *object, guint property_id, GValue *value, GParamSpec *pspec ); static void screem_view_size_request( GtkWidget *widget, GtkRequisition *requisition ); static void screem_view_size_allocate( GtkWidget *widget, GtkAllocation *allocation ); static void screem_view_class_init( ScreemViewClass *klass ) { GObjectClass *object_class; GtkWidgetClass *widget_class; GParamSpec *pspec; object_class = G_OBJECT_CLASS( klass ); widget_class = (GtkWidgetClass *)klass; object_class->finalize = screem_view_finalize; object_class->get_property = screem_view_get_prop; object_class->set_property = screem_view_set_prop; widget_class->size_request = screem_view_size_request; widget_class->size_allocate = screem_view_size_allocate; pspec = g_param_spec_pointer( "window", "window", "window", G_PARAM_READABLE | G_PARAM_WRITABLE ); g_object_class_install_property( G_OBJECT_CLASS( object_class ), PROP_WINDOW, pspec ); pspec = g_param_spec_object( "site", "site", "site", SCREEM_TYPE_SITE, G_PARAM_READABLE ); g_object_class_install_property( G_OBJECT_CLASS( object_class ), PROP_SITE, pspec ); pspec = g_param_spec_object( "page", "page", "page", SCREEM_TYPE_PAGE, G_PARAM_READABLE | G_PARAM_WRITABLE ); g_object_class_install_property( G_OBJECT_CLASS( object_class ), PROP_PAGE, pspec ); pspec = g_param_spec_boolean( "online", "online", "online", FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE ); g_object_class_install_property( G_OBJECT_CLASS( object_class ), PROP_ONLINE, pspec ); pspec = g_param_spec_object( "uimanager", "uimanager", "uimanager", GTK_TYPE_UI_MANAGER, G_PARAM_READABLE ); g_object_class_install_property( G_OBJECT_CLASS( object_class ), PROP_UIMANAGER, pspec ); pspec = g_param_spec_object( "actions", "actions", "actions", GTK_TYPE_ACTION_GROUP, G_PARAM_READABLE ); g_object_class_install_property( G_OBJECT_CLASS( object_class ), PROP_ACTIONS, pspec ); pspec = g_param_spec_object( "app", "app", "app", SCREEM_TYPE_APPLICATION, G_PARAM_READABLE ); g_object_class_install_property( G_OBJECT_CLASS( object_class ), PROP_APP, pspec ); } static void screem_view_init( ScreemView *view ) { view->priv = g_new0( ScreemViewPrivate, 1 ); } static void screem_view_finalize( GObject *sview ) { ScreemView *view; view = SCREEM_VIEW( sview ); g_free( view->priv ); G_OBJECT_CLASS( screem_view_parent_class )->finalize( sview ); } static void screem_view_set_prop( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec ) { ScreemView *view; view = SCREEM_VIEW( object ); switch( property_id ) { case PROP_WINDOW: view->priv->window = SCREEM_WINDOW( g_value_get_pointer( value ) ); break; case PROP_PAGE: view->priv->page = SCREEM_PAGE( g_value_get_object(value) ); break; case PROP_ONLINE: view->priv->online = g_value_get_boolean( value ); break; } } static void screem_view_get_prop( GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { ScreemView *view; ScreemWindow *window; ScreemSite *site; ScreemPage *page; GtkUIManager *ui; GtkActionGroup *group; ScreemApplication *app; view = SCREEM_VIEW( object ); window = view->priv->window; if( window ) { site = screem_window_get_current( window ); page = screem_window_get_document( window ); ui = GTK_UI_MANAGER( window->merge ); group = window->action_group; app = window->application; } else { site = NULL; page = view->priv->page; ui = NULL; group = NULL; app = NULL; } switch( property_id ) { case PROP_WINDOW: g_value_set_pointer( value, view->priv->window ); break; case PROP_SITE: g_value_set_object( value, site ); break; case PROP_PAGE: g_value_set_object( value, page ); break; case PROP_ONLINE: g_value_set_boolean( value, view->priv->online ); break; case PROP_UIMANAGER: g_value_set_object( value, ui ); break; case PROP_ACTIONS: g_value_set_object( value, group ); break; case PROP_APP: g_value_set_object( value, app ); break; } } static void screem_view_size_request( GtkWidget *widget, GtkRequisition *requisition ) { GtkBin *bin; bin = GTK_BIN (widget); requisition->width = GTK_CONTAINER( widget )->border_width * 2; requisition->height = GTK_CONTAINER( widget )->border_width * 2; if( bin->child && GTK_WIDGET_VISIBLE( bin->child ) ) { GtkRequisition child_requisition; gtk_widget_size_request( bin->child, &child_requisition ); requisition->width += child_requisition.width; requisition->height += child_requisition.height; } } static void screem_view_size_allocate( GtkWidget *widget, GtkAllocation *allocation ) { GtkBin *bin; GtkAllocation child_allocation; bin = GTK_BIN( widget ); widget->allocation = *allocation; if( bin->child ) { child_allocation.x = allocation->x + GTK_CONTAINER( widget )->border_width; child_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width; child_allocation.width = MAX( allocation->width - GTK_CONTAINER( widget )->border_width * 2, 0); child_allocation.height = MAX( allocation->height - GTK_CONTAINER (widget)->border_width * 2, 0); gtk_widget_size_allocate( bin->child, &child_allocation ); } }