thunar-usagebars/thunar/thunar-icon-view.c
4aiman e969f94310 thunar 4.20.2 upstream
Tree of tag thunar-4.20.2 (commit 11a519f) from https://gitlab.xfce.org/xfce/thunar.
Upstream history is not included here to keep the repository small.
2026-11-03 22:42:48 +03:00

275 lines
8.8 KiB
C

/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
*
* 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., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "thunar/thunar-icon-view.h"
#include "thunar/thunar-private.h"
/* Property identifiers */
enum
{
PROP_0,
PROP_TEXT_BESIDE_ICONS,
};
static void
thunar_icon_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static AtkObject *
thunar_icon_view_get_accessible (GtkWidget *widget);
static void
thunar_icon_view_style_set (GtkWidget *widget,
GtkStyle *previous_style);
static void
thunar_icon_view_set_consistent_horizontal_spacing (ThunarIconView *icon_view);
static void
thunar_icon_view_zoom_level_changed (ThunarStandardView *standard_view);
struct _ThunarIconViewClass
{
ThunarAbstractIconViewClass __parent__;
};
struct _ThunarIconView
{
ThunarAbstractIconView __parent__;
};
G_DEFINE_TYPE (ThunarIconView, thunar_icon_view, THUNAR_TYPE_ABSTRACT_ICON_VIEW)
static void
thunar_icon_view_class_init (ThunarIconViewClass *klass)
{
ThunarStandardViewClass *thunarstandard_view_class;
GtkWidgetClass *gtkwidget_class;
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = thunar_icon_view_set_property;
gtkwidget_class = GTK_WIDGET_CLASS (klass);
gtkwidget_class->style_set = thunar_icon_view_style_set;
gtkwidget_class->get_accessible = thunar_icon_view_get_accessible;
thunarstandard_view_class = THUNAR_STANDARD_VIEW_CLASS (klass);
thunarstandard_view_class->zoom_level_property_name = "last-icon-view-zoom-level";
/**
* ThunarIconView::text-beside-icons:
*
* Write-only property to specify whether text should be
* display besides the icon rather than below.
**/
g_object_class_install_property (gobject_class,
PROP_TEXT_BESIDE_ICONS,
g_param_spec_boolean ("text-beside-icons",
"text-beside-icons",
"text-beside-icons",
FALSE,
EXO_PARAM_WRITABLE));
}
static void
thunar_icon_view_init (ThunarIconView *icon_view)
{
/* setup the icon renderer */
g_object_set (G_OBJECT (THUNAR_STANDARD_VIEW (icon_view)->icon_renderer),
"ypad", 1u,
NULL);
/* setup the name renderer */
g_object_set (G_OBJECT (THUNAR_STANDARD_VIEW (icon_view)->name_renderer),
"wrap-mode", PANGO_WRAP_WORD_CHAR,
NULL);
/* synchronize the "text-beside-icons" property with the global preference */
g_object_bind_property (G_OBJECT (THUNAR_STANDARD_VIEW (icon_view)->preferences),
"misc-text-beside-icons",
G_OBJECT (icon_view),
"text-beside-icons",
G_BINDING_SYNC_CREATE);
}
static void
thunar_icon_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ThunarStandardView *standard_view = THUNAR_STANDARD_VIEW (object);
switch (prop_id)
{
case PROP_TEXT_BESIDE_ICONS:
if (G_UNLIKELY (g_value_get_boolean (value)))
{
exo_icon_view_set_orientation (EXO_ICON_VIEW (gtk_bin_get_child (GTK_BIN (standard_view))), GTK_ORIENTATION_HORIZONTAL);
g_object_set (G_OBJECT (standard_view->name_renderer), "wrap-width", 128, "yalign", 0.5f, "xalign", 0.0f, "alignment", PANGO_ALIGN_LEFT, NULL);
/* disconnect the "zoom-level" signal handler, since we're using a fixed wrap-width here */
g_signal_handlers_disconnect_by_func (object, thunar_icon_view_zoom_level_changed, NULL);
/* reset consistent horizontal spacing */
thunar_icon_view_set_consistent_horizontal_spacing (THUNAR_ICON_VIEW (standard_view));
}
else
{
exo_icon_view_set_orientation (EXO_ICON_VIEW (gtk_bin_get_child (GTK_BIN (standard_view))), GTK_ORIENTATION_VERTICAL);
g_object_set (G_OBJECT (standard_view->name_renderer), "yalign", 0.0f, "xalign", 0.5f, "alignment", PANGO_ALIGN_CENTER, NULL);
/* connect the "zoom-level" signal handler as the wrap-width is now synced with the "zoom-level" */
g_signal_connect (object, "notify::zoom-level", G_CALLBACK (thunar_icon_view_zoom_level_changed), NULL);
thunar_icon_view_zoom_level_changed (standard_view);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static AtkObject *
thunar_icon_view_get_accessible (GtkWidget *widget)
{
AtkObject *object;
/* query the atk object for the icon view class */
object = (*GTK_WIDGET_CLASS (thunar_icon_view_parent_class)->get_accessible) (widget);
/* set custom Atk properties for the icon view */
if (G_LIKELY (object != NULL))
{
atk_object_set_description (object, _("Icon based directory listing"));
atk_object_set_name (object, _("Icon view"));
atk_object_set_role (object, ATK_ROLE_DIRECTORY_PANE);
}
return object;
}
static void
thunar_icon_view_style_set (GtkWidget *widget,
GtkStyle *previous_style)
{
/* call the parent handler */
(*GTK_WIDGET_CLASS (thunar_icon_view_parent_class)->style_set) (widget, previous_style);
/* (re)set consistent horizontal spacing */
thunar_icon_view_set_consistent_horizontal_spacing (THUNAR_ICON_VIEW (widget));
}
static void
thunar_icon_view_set_consistent_horizontal_spacing (ThunarIconView *icon_view)
{
ThunarStandardView *standard_view = THUNAR_STANDARD_VIEW (icon_view);
ExoIconView *exo_icon_view = EXO_ICON_VIEW (gtk_bin_get_child (GTK_BIN (standard_view)));
gint wrap_width;
gint xpad;
gint column_spacing;
if (exo_icon_view_get_orientation (exo_icon_view) == GTK_ORIENTATION_HORIZONTAL)
{
/* reset consistent horizontal spacing if text is beside icon */
exo_icon_view_set_item_width (exo_icon_view, -1);
return;
}
g_object_get (G_OBJECT (standard_view->name_renderer), "wrap-width", &wrap_width, NULL);
gtk_cell_renderer_get_padding (standard_view->name_renderer, &xpad, NULL);
column_spacing = exo_icon_view_get_column_spacing (exo_icon_view);
/* set consistent horizontal spacing */
exo_icon_view_set_item_width (exo_icon_view, wrap_width + MAX (0, xpad * 2 - column_spacing));
}
static void
thunar_icon_view_zoom_level_changed (ThunarStandardView *standard_view)
{
gint wrap_width;
ExoIconView *exo_icon_view;
ThunarZoomLevel zoom_level;
_thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
exo_icon_view = EXO_ICON_VIEW (gtk_bin_get_child (GTK_BIN (standard_view)));
zoom_level = thunar_view_get_zoom_level (THUNAR_VIEW (standard_view));
/* determine the "wrap-width" depending on the "zoom-level" */
switch (zoom_level)
{
case THUNAR_ZOOM_LEVEL_25_PERCENT:
wrap_width = 48;
break;
case THUNAR_ZOOM_LEVEL_38_PERCENT:
wrap_width = 64;
break;
case THUNAR_ZOOM_LEVEL_50_PERCENT:
wrap_width = 72;
break;
case THUNAR_ZOOM_LEVEL_75_PERCENT:
wrap_width = 112;
break;
default:
wrap_width = 128;
break;
}
/* set the new "wrap-width" for the text renderer */
g_object_set (G_OBJECT (standard_view->name_renderer), "wrap-width", wrap_width, NULL);
/* set consistent horizontal spacing */
thunar_icon_view_set_consistent_horizontal_spacing (THUNAR_ICON_VIEW (standard_view));
/* Like that rubber band selection can be done properly on high zoom levels */
/* Without margin adjustment it would be almost impossible to start the selection on the left */
exo_icon_view_set_margin (exo_icon_view, thunar_zoom_level_to_view_margin (zoom_level));
}