* hildon-widgets/hildon-scroll-area.c (hildon_scroll_area_destroy): one-instruction...
[hildon] / hildon-widgets / hildon-file-details-dialog.c
index 32686ba..c83e5c1 100644 (file)
  * 
  * This file contains API for Hildon File Details dialog.
  * 
-*/
+ */
 
-#include <gtk/gtkbox.h>
 #include <gtk/gtkcheckbutton.h>
 #include <gtk/gtklabel.h>
 #include <gtk/gtknotebook.h>
-#include <gtk/gtktable.h>
 #include <gtk/gtkhbox.h>
+#include <gtk/gtkvbox.h>
 #include <gtk/gtkimage.h>
+#include <gtk/gtkscrolledwindow.h>
 #include <time.h>
 #include <libintl.h>
 #include <sys/types.h>
@@ -45,6 +45,7 @@
 #include <hildon-widgets/hildon-caption.h>
 #include <hildon-widgets/hildon-file-system-model.h>
 #include <hildon-widgets/gtk-infoprint.h>
+#include <hildon-widgets/hildon-defines.h>
 #include "hildon-file-details-dialog.h"
 
 #ifdef HAVE_CONFIG_H
@@ -52,8 +53,6 @@
 #endif
 
 #define _(String) dgettext(PACKAGE, String)
-#define HILDON_MARGIN_DEFAULT 6
-#define HILDON_MARGIN_DOUBLE 12
 
 enum
 {
@@ -96,6 +95,8 @@ hildon_file_details_dialog_set_property( GObject *object, guint param_id,
 static void
 hildon_file_details_dialog_get_property( GObject *object, guint param_id,
                                                           GValue *value, GParamSpec *pspec );
+static void 
+hildon_file_details_dialog_response(GtkDialog *dialog, gint response_id);
 
 static GtkDialogClass *file_details_dialog_parent_class = NULL;
 
@@ -162,14 +163,14 @@ static void change_state(HildonFileDetailsDialog *self, gboolean readonly)
 
 /* Cancel changes if read-only is changed */
 static void 
-hildon_file_details_dialog_response(GtkWidget *widget, gint response_id, gpointer data)
+hildon_file_details_dialog_response(GtkDialog *dialog, gint response_id)
 {
     if (response_id == GTK_RESPONSE_CANCEL)
     {
       HildonFileDetailsDialog *self;
       gboolean state;
 
-      self = HILDON_FILE_DETAILS_DIALOG(widget);  
+      self = HILDON_FILE_DETAILS_DIALOG(dialog);  
       state = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(self->priv->file_readonly));
 
       if (state != self->priv->checkbox_original_state)
@@ -187,8 +188,19 @@ hildon_file_details_dialog_read_only_toggled(GtkWidget *widget, gpointer data)
 static void 
 hildon_file_details_dialog_map(GtkWidget *widget)
 {
+  HildonFileDetailsDialogPrivate *priv;
+
+  priv = HILDON_FILE_DETAILS_DIALOG(widget)->priv;
+
   GTK_WIDGET_CLASS(file_details_dialog_parent_class)->map(widget);
-  gtk_widget_grab_focus(HILDON_FILE_DETAILS_DIALOG(widget)->priv->ok_button);
+
+  if (gtk_notebook_get_show_tabs(priv->notebook))
+  {
+    gtk_notebook_set_current_page(priv->notebook, 0);
+    gtk_widget_grab_focus(GTK_WIDGET(priv->notebook));
+  }
+  else
+    gtk_widget_grab_focus(priv->ok_button);
 }
 
 static void
@@ -202,6 +214,8 @@ hildon_file_details_dialog_class_init(HildonFileDetailsDialogClass * klass)
     gobject_class->get_property = hildon_file_details_dialog_get_property;
     gobject_class->set_property = hildon_file_details_dialog_set_property;
     GTK_WIDGET_CLASS(klass)->map = hildon_file_details_dialog_map;
+    GTK_DIALOG_CLASS(klass)->response = hildon_file_details_dialog_response;
+
     g_type_class_add_private(klass, sizeof(HildonFileDetailsDialogPrivate));
 
   /**
@@ -213,7 +227,7 @@ hildon_file_details_dialog_class_init(HildonFileDetailsDialogClass * klass)
                                    g_param_spec_object("additional-tab",
                                    "Additional tab",
                                    "Tab to show additinal information",
-                                   GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+                                                      GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
   /**
    * HildonFileDetailsDialog:show_tabs:
    *
@@ -223,7 +237,7 @@ hildon_file_details_dialog_class_init(HildonFileDetailsDialogClass * klass)
                                    g_param_spec_boolean("show-tabs",
                                    "Show tab labels",
                                    "Do we want to show the tab label.",
-                                   FALSE, G_PARAM_READWRITE));
+                                   FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
   /**
    * HildonFileDetailsDialog:additional_tab_label:
    *
@@ -241,6 +255,20 @@ hildon_file_details_dialog_class_init(HildonFileDetailsDialogClass * klass)
                  HILDON_TYPE_FILE_SYSTEM_MODEL, G_PARAM_READWRITE));
 }
 
+/* This handler is needed to correctly position the scrollbar down. 
+   It doesn't happen automatically... */
+static gboolean 
+handle_focus(GtkWidget *widget, GtkDirectionType *dir, gpointer data)
+{
+  if (!GTK_WIDGET_HAS_FOCUS(widget))
+  {
+    GtkAdjustment *adj;
+    adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(data));
+    gtk_adjustment_set_value(adj, adj->upper - adj->page_size);
+  }
+
+  return FALSE;
+}
 
 static void
 hildon_file_details_dialog_init(HildonFileDetailsDialog *self)
@@ -249,7 +277,8 @@ hildon_file_details_dialog_init(HildonFileDetailsDialog *self)
     GtkWidget *caption_date, *caption_size, *caption_time;
     GtkWidget *caption_read, *caption_device;
     GtkWidget *hbox_location, *hbox_device;
-    GtkTable *table;
+    GtkWidget *vbox;
+    GtkWidget *scroll;
     GtkSizeGroup *group;
     GdkGeometry geometry;
 
@@ -260,7 +289,8 @@ hildon_file_details_dialog_init(HildonFileDetailsDialog *self)
           HILDON_TYPE_FILE_DETAILS_DIALOG, HildonFileDetailsDialogPrivate);
 
     priv->notebook = GTK_NOTEBOOK(gtk_notebook_new());
-    table = GTK_TABLE(gtk_table_new(6, 4, FALSE));
+    scroll = gtk_scrolled_window_new(NULL, NULL);
+    vbox = gtk_vbox_new(FALSE, 0);
     group = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
     
     priv->tab_label = gtk_label_new(_("sfil_ti_notebook_file"));
@@ -268,24 +298,6 @@ hildon_file_details_dialog_init(HildonFileDetailsDialog *self)
     gtk_object_sink(GTK_OBJECT(priv->tab_label));
     gtk_widget_show(priv->tab_label);
 
-    gtk_container_set_border_width(GTK_CONTAINER(table), 
-        HILDON_MARGIN_DEFAULT);
-    gtk_table_set_col_spacings(table, HILDON_MARGIN_DOUBLE);
-
-    /* Tab one */
-    caption_device = g_object_new(GTK_TYPE_LABEL, 
-        "label", _("sfil_fi_properties_device_prompt"), "xalign", 1.0f, NULL);
-    caption_location = g_object_new(GTK_TYPE_LABEL,
-        "label", _("sfil_fi_properties_location_prompt"), "xalign", 1.0f, NULL);
-    caption_name = g_object_new(GTK_TYPE_LABEL,
-        "label", _("ckdg_fi_properties_name_prompt"), "xalign", 1.0f, NULL);
-    caption_type = g_object_new(GTK_TYPE_LABEL, 
-        "label", _("ckdg_fi_properties_type_prompt"), "xalign", 1.0f, NULL);
-    caption_date = g_object_new(GTK_TYPE_LABEL,
-        "label", _("ckdg_fi_properties_date_prompt"), "xalign", 1.0f, NULL);
-    caption_time = g_object_new(GTK_TYPE_LABEL, 
-        "label", _("ckdg_fi_properties_time_prompt"), "xalign", 1.0f, NULL);
-
     priv->file_device = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
     priv->file_location = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
     priv->file_name = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
@@ -295,14 +307,6 @@ hildon_file_details_dialog_init(HildonFileDetailsDialog *self)
     priv->file_time = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
     priv->file_readonly = gtk_check_button_new();
 
-    /* We have to use caption control also for non-editable object, 
-        because sizings will fail otherwise */
-    caption_size = hildon_caption_new(group, _("ckdg_fi_properties_size_prompt"), 
-      priv->file_size, NULL, HILDON_CAPTION_OPTIONAL);
-    caption_read = hildon_caption_new(group, _("ckdg_fi_properties_read_only"), 
-      priv->file_readonly, NULL, HILDON_CAPTION_OPTIONAL);
-    g_object_unref(group);
-
     hbox_location = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT);
     hbox_device = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT);
 
@@ -314,40 +318,74 @@ hildon_file_details_dialog_init(HildonFileDetailsDialog *self)
     gtk_box_pack_start(GTK_BOX(hbox_device), priv->file_device_image, FALSE, TRUE, 0);
     gtk_box_pack_start(GTK_BOX(hbox_device), priv->file_device, TRUE, TRUE, 0);
 
-    /* Labels */
-    gtk_table_attach(table, caption_name, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, caption_type, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, caption_location, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, caption_device, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 0); 
-    gtk_table_attach(table, caption_date, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, caption_time, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, caption_size, 2, 3, 4, 5, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, caption_read, 2, 4, 5, 6, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
-
-    /* Data */
-    gtk_table_attach(table, priv->file_name, 1, 4, 0, 1, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, priv->file_type, 1, 4, 1, 2, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, hbox_location, 1, 4, 2, 3, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, hbox_device, 1, 4, 3, 4, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0); 
-    gtk_table_attach(table, priv->file_date, 1, 2, 4, 5, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
-    gtk_table_attach(table, priv->file_time, 1, 2, 5, 6, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
+    /* Tab one */
+    caption_name = hildon_caption_new(group, _("ckdg_fi_properties_name_prompt"), 
+      priv->file_name, NULL, HILDON_CAPTION_OPTIONAL);
+    caption_type = hildon_caption_new(group, _("ckdg_fi_properties_type_prompt"), 
+      priv->file_type, NULL, HILDON_CAPTION_OPTIONAL);
+    caption_location = hildon_caption_new(group, _("sfil_fi_properties_location_prompt"), 
+      hbox_location, NULL, HILDON_CAPTION_OPTIONAL);
+    caption_device = hildon_caption_new(group, _("sfil_fi_properties_device_prompt"), 
+      hbox_device, NULL, HILDON_CAPTION_OPTIONAL);
+    caption_date = hildon_caption_new(group, _("ckdg_fi_properties_date_prompt"), 
+      priv->file_date, NULL, HILDON_CAPTION_OPTIONAL);
+    caption_time = hildon_caption_new(group, _("ckdg_fi_properties_time_prompt"), 
+      priv->file_time, NULL, HILDON_CAPTION_OPTIONAL);
+    caption_size = hildon_caption_new(group, _("ckdg_fi_properties_size_prompt"), 
+      priv->file_size, NULL, HILDON_CAPTION_OPTIONAL);
+    caption_read = hildon_caption_new(group, _("ckdg_fi_properties_read_only"), 
+      priv->file_readonly, NULL, HILDON_CAPTION_OPTIONAL);
+
+    hildon_caption_set_separator(HILDON_CAPTION(caption_name), "");
+    hildon_caption_set_separator(HILDON_CAPTION(caption_type), "");
+    hildon_caption_set_separator(HILDON_CAPTION(caption_location), "");
+    hildon_caption_set_separator(HILDON_CAPTION(caption_device), "");
+    hildon_caption_set_separator(HILDON_CAPTION(caption_date), "");
+    hildon_caption_set_separator(HILDON_CAPTION(caption_time), "");
+    hildon_caption_set_separator(HILDON_CAPTION(caption_size), "");
+    hildon_caption_set_separator(HILDON_CAPTION(caption_read), "");
+
+    g_object_unref(group);
+
+    gtk_box_pack_start(GTK_BOX(vbox), caption_name, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), caption_type, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), caption_location, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), caption_device, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), caption_date, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), caption_time, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), caption_size, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), caption_read, FALSE, TRUE, 0);
+
+    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), vbox);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), 
+        GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+    gtk_container_set_border_width(GTK_CONTAINER(scroll), 
+        HILDON_MARGIN_DEFAULT);
+    /* Both scrolled window and viewport have separate shadows... */
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll),
+        GTK_SHADOW_NONE);
+    gtk_viewport_set_shadow_type(
+        GTK_VIEWPORT(gtk_bin_get_child(GTK_BIN(scroll))),
+        GTK_SHADOW_NONE);
 
     /* Populate dialog */
-    gtk_notebook_append_page(priv->notebook, GTK_WIDGET(table), 
-      gtk_label_new(_("sfil_ti_notebook_common")));
+    gtk_notebook_append_page(priv->notebook, scroll,
+                            gtk_label_new(_("sfil_ti_notebook_common")));
 
     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(self)->vbox),
-                       GTK_WIDGET(priv->notebook), FALSE, TRUE, 0);
+                       GTK_WIDGET(priv->notebook), TRUE, TRUE, 0);
 
     /* From widget specs, generic dialog size */
     geometry.min_width = 133;
     geometry.max_width = 602;
-    geometry.min_height = 120;
-    geometry.max_height = 240;
+    /* Scrolled windows do not ask space for whole contents in size_request.
+       So, we must force the dialog to have larger than minimum size */
+    geometry.min_height = 240 + (2 * HILDON_MARGIN_DEFAULT);
+    geometry.max_height = 240 + (2 * HILDON_MARGIN_DEFAULT);
 
     gtk_window_set_geometry_hints(GTK_WINDOW(self),
-                        GTK_WIDGET(priv->notebook), &geometry,
-                        GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
+                                 GTK_WIDGET(priv->notebook), &geometry,
+                                 GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
 
     gtk_widget_show_all(GTK_WIDGET(priv->notebook));
     priv->ok_button = gtk_dialog_add_button(GTK_DIALOG(self),
@@ -359,11 +397,11 @@ hildon_file_details_dialog_init(HildonFileDetailsDialog *self)
     gtk_dialog_set_default_response(GTK_DIALOG(self),
                           GTK_RESPONSE_OK);
 
-    g_signal_connect(self, "response", 
-      G_CALLBACK(hildon_file_details_dialog_response), NULL);
     priv->toggle_handler = g_signal_connect(priv->file_readonly, "toggled", 
       G_CALLBACK(hildon_file_details_dialog_read_only_toggled), 
       self);
+    g_signal_connect(priv->file_readonly, "focus",
+      G_CALLBACK(handle_focus), scroll);
 }
 
 static void
@@ -385,23 +423,30 @@ hildon_file_details_dialog_set_property( GObject *object, guint param_id,
     {
       gtk_notebook_set_show_tabs(notebook, g_value_get_boolean(value));
       gtk_notebook_set_show_border(notebook, g_value_get_boolean(value));
-/*      g_assert(gtk_notebook_get_n_pages(notebook) == 2);*/
       break;
     }
     case PROP_ADDITIONAL_TAB:
     {
       GtkWidget *widget = g_value_get_object(value);
-
+      GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL);
+      
       if (gtk_notebook_get_n_pages(notebook) == 2)
         gtk_notebook_remove_page(notebook, 1);
 
       if (widget == NULL)
       {
-        widget = gtk_label_new(_("sfil_ia_filetype_no_details"));
+        widget = g_object_new(GTK_TYPE_LABEL, 
+            "label", _("sfil_ia_filetype_no_details"), "yalign", 0.0f, NULL);
         gtk_widget_show(widget);
       }
 
-      gtk_notebook_append_page(notebook, widget, priv->tab_label);
+      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
+                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+      gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), widget);
+      gtk_viewport_set_shadow_type(GTK_VIEWPORT(GTK_BIN(sw)->child),
+                                   GTK_SHADOW_NONE);
+      gtk_widget_show_all(sw);
+      gtk_notebook_append_page(notebook, sw, priv->tab_label);
       gtk_notebook_set_current_page(notebook, 0);
       break;
     }
@@ -413,7 +458,7 @@ hildon_file_details_dialog_set_property( GObject *object, guint param_id,
       HildonFileSystemModel *new_model = g_value_get_object(value);
       if (new_model != priv->model)
       {
-        if (priv->model)
+        if (G_IS_OBJECT(priv->model))
           g_object_unref(priv->model);
         priv->model = new_model;
         if (new_model)
@@ -463,9 +508,12 @@ static void hildon_file_details_dialog_finalize(GObject * object)
   g_return_if_fail(HILDON_IS_FILE_DETAILS_DIALOG(object));
 
   priv = HILDON_FILE_DETAILS_DIALOG(object)->priv;
-  g_object_unref(priv->model);
-  g_object_unref(priv->tab_label);
-  gtk_tree_row_reference_free(priv->active_file);
+  if (G_IS_OBJECT(priv->model))
+    g_object_unref(priv->model);
+  if (G_IS_OBJECT(priv->tab_label))
+    g_object_unref(priv->tab_label);
+  if (priv->active_file)
+    gtk_tree_row_reference_free(priv->active_file);
     
   G_OBJECT_CLASS(file_details_dialog_parent_class)->finalize(object);
 }
@@ -487,6 +535,7 @@ static void hildon_file_details_dialog_finalize(GObject * object)
  *
  * Returns: a new #HildonFileDetailsDialog.
  */
+#ifndef HILDON_DISABLE_DEPRECATED
 GtkWidget *hildon_file_details_dialog_new(GtkWindow * parent,
                                           const gchar * filename)
 {
@@ -510,7 +559,7 @@ GtkWidget *hildon_file_details_dialog_new(GtkWindow * parent,
 
   return GTK_WIDGET(dialog);
 }
-
+#endif
 /**
  * hildon_file_details_dialog_new_with_model:
  * @parent: the parent window.
@@ -579,7 +628,7 @@ void hildon_file_details_dialog_set_file_iter(HildonFileDetailsDialog *self, Gtk
     -1);
 
   g_object_set(self->priv->file_name, "label", name, NULL);
-  g_object_set(self->priv->file_type, "label", mime, NULL);
+  g_object_set(self->priv->file_type, "label", _(mime), NULL);
 
   if (size < 1024)
     g_snprintf(buffer, sizeof(buffer),
@@ -625,7 +674,8 @@ void hildon_file_details_dialog_set_file_iter(HildonFileDetailsDialog *self, Gtk
     gtk_image_set_from_pixbuf(GTK_IMAGE(self->priv->file_location_image), 
       location_icon);
 
-    g_object_unref(location_icon);
+    if (G_IS_OBJECT(location_icon))
+      g_object_unref(location_icon);
     g_free(location_name);
 
     /* Go upwards in model until we find a device node */
@@ -652,7 +702,8 @@ void hildon_file_details_dialog_set_file_iter(HildonFileDetailsDialog *self, Gtk
     gtk_image_set_from_pixbuf(GTK_IMAGE(self->priv->file_device_image), 
       location_icon);
 
-    g_object_unref(location_icon);
+    if (G_IS_OBJECT(location_icon))
+      g_object_unref(location_icon);
     g_free(location_name);
     g_free(parent_path);
   }