aboutsummaryrefslogblamecommitdiffstats
path: root/mail/subscribe-control.c
blob: 4e1f85eff243a97ee87d381338c37d4da9417413 (plain) (tree)




















                                                                           
                        





                                                                        
                                                                        
                                                                        























                                                                        





                            













                                                          














                                                                           


                                                        





                                                                         

 















                                                                           


                                                          











                                                                         




























































































































                                                                               
                                                                       




                                               
                                                         
























































                                                                                                      


                                                               
                                                              

                                                   


                                               
                                                                             



























                                                                                                 



                                                                         
























































































                                                                                                                                         
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * subscribe-control.c: Subscribe control top level component
 *
 * Author:
 *   Chris Toshok (toshok@helixcode.com)
 *
 * (C) 2000 Helix Code, Inc.
 */
#include <config.h>
#include <gnome.h>
#include "subscribe-control.h"
#include "e-util/e-html-utils.h"
#include <gtkhtml/gtkhtml.h>
#include <gal/util/e-util.h>
#include <gal/e-table/e-cell-text.h>
#include <gal/e-table/e-cell-tree.h>
#include <gal/e-table/e-cell-toggle.h>
#include <gal/e-table/e-table-scrolled.h>
#include <gal/e-table/e-tree-simple.h>

#include "art/empty.xpm"
#include "art/mark.xpm"

#define PARENT_TYPE (gtk_table_get_type ())

#define ETABLE_SPEC "<ETableSpecification>                             \
    <columns-shown>                                    \
        <column> 0 </column>                       \
        <column> 1 </column>                       \
        <column> 2 </column>                       \
    </columns-shown>                                   \
    <grouping></grouping>                                         \
</ETableSpecification>"

enum {
    COL_FOLDER_NAME,
    COL_FOLDER_SUBSCRIBED,
    COL_FOLDER_DESCRIPTION,
    COL_LAST
};

/*
 * Virtual Column list:
 * 0   Folder Name
 * 1   Subscribed
 * 2   Description
 */
char *headers [COL_LAST] = {
  "Folder",
  "Subscribed",
  "Description",
};

/* per node structure */
typedef struct {
    gboolean subscribed;
} SubscribeData;


static GtkObjectClass *subscribe_control_parent_class;

void
subscribe_select_all (BonoboUIHandler *uih,
              void *user_data, const char *path)
{
}

void
subscribe_unselect_all (BonoboUIHandler *uih,
            void *user_data, const char *path)
{
}

static void
subscribe_folder_foreach (int model_row, gpointer closure)
{
    SubscribeControl *sc = SUBSCRIBE_CONTROL (closure);
    ETreePath *node = e_tree_model_node_at_row (sc->model, model_row);
    SubscribeData *data = e_tree_model_node_get_data (sc->model, node);

    printf ("subscribe: row %d, node_data %p\n", model_row,
        e_tree_model_node_get_data (sc->model, node));

    data->subscribed = TRUE;

    e_tree_model_node_changed (sc->model, node);
}

void
subscribe_folder (GtkWidget *widget, gpointer user_data)
{
    SubscribeControl *sc = SUBSCRIBE_CONTROL (user_data);

    printf ("subscribe_folder called\n");

    e_table_selected_row_foreach (E_TABLE_SCROLLED(sc->table)->table,
                      subscribe_folder_foreach, sc);
}

static void
unsubscribe_folder_foreach (int model_row, gpointer closure)
{
    SubscribeControl *sc = SUBSCRIBE_CONTROL (closure);
    ETreePath *node = e_tree_model_node_at_row (sc->model, model_row);
    SubscribeData *data = e_tree_model_node_get_data (sc->model, node);

    printf ("unsubscribe: row %d, node_data %p\n", model_row,
        e_tree_model_node_get_data (sc->model, node));

    data->subscribed = FALSE;

    e_tree_model_node_changed (sc->model, node);
}


void
unsubscribe_folder (GtkWidget *widget, gpointer user_data)
{
    SubscribeControl *sc = SUBSCRIBE_CONTROL (user_data);

    printf ("unsubscribe_folder called\n");

    e_table_selected_row_foreach (E_TABLE_SCROLLED(sc->table)->table,
                      unsubscribe_folder_foreach, sc);
}

void
subscribe_refresh_list (GtkWidget *widget, gpointer user_data)
{
    printf ("subscribe_refresh_list\n");
}

gboolean
subscribe_control_set_uri (SubscribeControl *subscribe_control,
               const char *uri)
{
    printf ("set_uri (%s) called\n", uri);
    return TRUE;
}


/* HTML Helpers */
static void
html_size_req (GtkWidget *widget, GtkRequisition *requisition)
{
    if (GTK_LAYOUT (widget)->height > 90)
        requisition->height = 90;
    else
        requisition->height = GTK_LAYOUT (widget)->height;
}

/* Returns a GtkHTML which is already inside a GtkScrolledWindow. If
 * @white is TRUE, the GtkScrolledWindow will be inside a GtkFrame.
 */
static GtkWidget *
html_new (gboolean white)
{
    GtkWidget *html, *scrolled, *frame;
    GtkStyle *style;
    
    html = gtk_html_new ();
    GTK_LAYOUT (html)->height = 0;
    gtk_signal_connect (GTK_OBJECT (html), "size_request",
                GTK_SIGNAL_FUNC (html_size_req), NULL);
    gtk_html_set_editable (GTK_HTML (html), FALSE);
    style = gtk_rc_get_style (html);
    if (style) {
        gtk_html_set_default_background_color (GTK_HTML (html),
                               white ? &style->white :
                               &style->bg[0]);
    }
    gtk_widget_set_sensitive (html, FALSE);
    scrolled = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
                    GTK_POLICY_NEVER,
                    GTK_POLICY_NEVER);
    gtk_container_add (GTK_CONTAINER (scrolled), html);
    
    if (white) {
        frame = gtk_frame_new (NULL);
        gtk_frame_set_shadow_type (GTK_FRAME (frame),
                       GTK_SHADOW_ETCHED_IN);
        gtk_container_add (GTK_CONTAINER (frame), scrolled);
        gtk_widget_show_all (frame);
    } else
        gtk_widget_show_all (scrolled);
    
    return html;
}

static void
put_html (GtkHTML *html, char *text)
{
    GtkHTMLStream *handle;
    
    text = e_text_to_html (text, (E_TEXT_TO_HTML_CONVERT_NL |
                      E_TEXT_TO_HTML_CONVERT_SPACES |
                      E_TEXT_TO_HTML_CONVERT_URLS));
    handle = gtk_html_begin (html);
    gtk_html_write (html, handle, "<HTML><BODY>", 12);
    gtk_html_write (html, handle, text, strlen (text));
    gtk_html_write (html, handle, "</BODY></HTML>", 14);
    g_free (text);
    gtk_html_end (html, handle, GTK_HTML_STREAM_OK);
}



/* etable stuff for the subscribe ui */

static int
etable_col_count (ETableModel *etm, void *data)
{
    return COL_LAST;
}

static void*
etable_duplicate_value (ETableModel *etm, int col, const void *val, void *data)
{
    return g_strdup (val);
}

static void
etable_free_value (ETableModel *etm, int col, void *val, void *data)
{
    g_free (val);
}

static void*
etable_init_value (ETableModel *etm, int col, void *data)
{
    return g_strdup ("");
}

static gboolean
etable_value_is_empty (ETableModel *etm, int col, const void *val, void *data)
{
    return !(val && *(char *)val);
}

static char*
etable_value_to_string (ETableModel *etm, int col, const void *val, void *data)
{
    return g_strdup(val);
}

static GdkPixbuf*
etree_icon_at (ETreeModel *etree, ETreePath *path, void *model_data)
{
    return NULL; /* XXX no icons for now */
}

static void*
etree_value_at (ETreeModel *etree, ETreePath *path, int col, void *model_data)
{
    SubscribeData *data = e_tree_model_node_get_data (etree, path);
    if (col == COL_FOLDER_NAME)
        return "Folder Name";
    else if (col == COL_FOLDER_DESCRIPTION)
        return "Folder Description";
    else /* COL_FOLDER_SUBSCRIBED */
        return GINT_TO_POINTER(data->subscribed);
}

static void
etree_set_value_at (ETreeModel *etree, ETreePath *path, int col, const void *val, void *model_data)
{
    /* nothing */
}

static gboolean
etree_is_editable (ETreeModel *etree, ETreePath *path, int col, void *model_data)
{
    return FALSE;
}



#define EXAMPLE_DESCR "And the beast shall come forth surrounded by a roiling cloud of vengeance.\n" \
"  The house of the unbelievers shall be razed and they shall be scorched to the\n" \
"          earth. Their tags shall blink until the end of days. \n" \
"                 from The Book of Mozilla, 12:10"

static void
subscribe_control_gui_init (SubscribeControl *sc)
{
    int i;
    ECell *cells[3];
    ETableHeader *e_table_header;
    GdkPixbuf *toggles[2];

    sc->description = html_new (TRUE);
    put_html (GTK_HTML (sc->description), EXAMPLE_DESCR);

    gtk_table_attach (
        GTK_TABLE (sc), sc->description->parent->parent,
        0, 1, 0, 1,
        GTK_FILL | GTK_EXPAND,
        0,
        0, 0);

    sc->model = e_tree_simple_new (etable_col_count,
                       etable_duplicate_value,
                       etable_free_value,
                       etable_init_value,
                       etable_value_is_empty,
                       etable_value_to_string,
                       etree_icon_at,
                       etree_value_at,
                       etree_set_value_at,
                       etree_is_editable,
                       sc);

    sc->root = e_tree_model_node_insert (sc->model, NULL,
                         0, NULL);

    e_tree_model_root_node_set_visible (sc->model, FALSE);


    for (i = 0; i < 100; i ++) {
        SubscribeData *data = g_new (SubscribeData, 1);
        data->subscribed = FALSE;
        e_tree_model_node_insert (sc->model, sc->root,
                      0, data);
    }

    e_table_header = e_table_header_new ();

    toggles[0] = gdk_pixbuf_new_from_xpm_data ((const char **)empty_xpm);
    toggles[1] = gdk_pixbuf_new_from_xpm_data ((const char **)mark_xpm);

    cells[2] = e_cell_text_new (E_TABLE_MODEL(sc->model), NULL, GTK_JUSTIFY_LEFT);
    cells[1] = e_cell_toggle_new (0, 2, toggles);
    cells[0] = e_cell_tree_new (E_TABLE_MODEL(sc->model),
                    NULL, NULL,
                    /*tree_expanded_pixbuf, tree_unexpanded_pixbuf,*/
                    TRUE, cells[2]);

    for (i = 0; i < COL_LAST; i++) {
        /* Create the column. */
        ETableCol *ecol;

        if (i == 1)
            ecol = e_table_col_new_with_pixbuf (i, toggles[1],
                                0, gdk_pixbuf_get_width (toggles[1]),
                                cells[i], g_str_compare, FALSE);
        else 
            ecol = e_table_col_new (i, headers [i],
                        80, 20,
                        cells[i],
                        g_str_compare, TRUE);
        /* Add it to the header. */
        e_table_header_add_column (e_table_header, ecol, i);
    }

    sc->table = e_table_scrolled_new (e_table_header, E_TABLE_MODEL(sc->model), ETABLE_SPEC);

    gtk_object_set (GTK_OBJECT (E_TABLE_SCROLLED (sc->table)->table),
            "cursor_mode", E_TABLE_CURSOR_LINE,
            NULL);

    gtk_table_attach (
        GTK_TABLE (sc), sc->table,
        0, 1, 1, 3,
        GTK_FILL | GTK_EXPAND,
        GTK_FILL | GTK_EXPAND,
        0, 0);

    gtk_widget_show_all (GTK_WIDGET(sc));
}

static void
subscribe_control_destroy (GtkObject *object)
{
    SubscribeControl *subscribe_control;
    CORBA_Environment ev;

    subscribe_control = SUBSCRIBE_CONTROL (object);

    CORBA_exception_init (&ev);

    if (subscribe_control->shell != CORBA_OBJECT_NIL)
        CORBA_Object_release (subscribe_control->shell, &ev);

    CORBA_exception_free (&ev);

    subscribe_control_parent_class->destroy (object);
}

static void
subscribe_control_class_init (GtkObjectClass *object_class)
{
    object_class->destroy = subscribe_control_destroy;

    subscribe_control_parent_class = gtk_type_class (PARENT_TYPE);
}

static void
subscribe_control_init (GtkObject *object)
{
}

static void
subscribe_control_construct (GtkObject *object)
{
    SubscribeControl *sc = SUBSCRIBE_CONTROL (object);

    /*
     * Setup parent class fields.
     */ 
    GTK_TABLE (sc)->homogeneous = FALSE;
    gtk_table_resize (GTK_TABLE (sc), 1, 2);

    /*
     * Our instance data
     */

    subscribe_control_gui_init (sc);
}

GtkWidget *
subscribe_control_new (const Evolution_Shell shell)
{
    static int serial = 0;
    CORBA_Environment ev;
    SubscribeControl *subscribe_control;

    CORBA_exception_init (&ev);

    subscribe_control = gtk_type_new (subscribe_control_get_type ());

    subscribe_control_construct (GTK_OBJECT (subscribe_control));
    subscribe_control->uri = NULL;
    subscribe_control->serial = serial++;

    subscribe_control->shell = CORBA_Object_duplicate (shell, &ev);
    if (ev._major != CORBA_NO_EXCEPTION) {
        subscribe_control->shell = CORBA_OBJECT_NIL;
        gtk_widget_destroy (GTK_WIDGET (subscribe_control));
        CORBA_exception_free (&ev);
        return NULL;
    }

    CORBA_exception_free (&ev);

    return GTK_WIDGET (subscribe_control);
}

E_MAKE_TYPE (subscribe_control, "SubscribeControl", SubscribeControl, subscribe_control_class_init, subscribe_control_init, PARENT_TYPE);