[Xfce4-commits] <design:master> More work on the mockup. Separators, markup, custom item renderer.
Jannis Pohlmann
noreply at xfce.org
Sun May 29 22:46:01 CEST 2011
Updating branch refs/heads/master
to e8cb4393724fdddd4f846a02740a04475235b9be (commit)
from d97b5a3e27b4a3f124a8a8c1ac97727d8b2e012b (commit)
commit e8cb4393724fdddd4f846a02740a04475235b9be
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Sun May 29 22:43:49 2011 +0200
More work on the mockup. Separators, markup, custom item renderer.
.../treeview-mockup/vala/mockup.vala | 399 ++++++++++++++++++--
1 files changed, 365 insertions(+), 34 deletions(-)
diff --git a/thunar/shortcuts-pane/treeview-mockup/vala/mockup.vala b/thunar/shortcuts-pane/treeview-mockup/vala/mockup.vala
index 6c38346..5bf1d66 100644
--- a/thunar/shortcuts-pane/treeview-mockup/vala/mockup.vala
+++ b/thunar/shortcuts-pane/treeview-mockup/vala/mockup.vala
@@ -71,16 +71,36 @@ public class Category : GLib.Object {
get { return _items; }
}
- public Category (string name) {
+ public Category (string? name) {
this.name = name;
}
}
+public class SeparatorCategory : Category {
+ public SeparatorCategory () {
+ base (null);
+ }
+}
+
+
public class ShortcutsModel : GLib.Object, TreeModel {
- public static enum Column { ICON, NAME, ACTION_WIDGET }
- private static Type[] ColumnTypes = { typeof (Icon), typeof (string), typeof (Button) };
+ public static enum Column {
+ ICON,
+ NAME,
+ ACTION_WIDGET,
+ SEPARATOR,
+ SENSITIVE,
+ }
+
+ private static Type[] ColumnTypes = {
+ typeof (Icon),
+ typeof (string),
+ typeof (Button),
+ typeof (bool),
+ typeof (bool)
+ };
private GenericArray<Category> categories = new GenericArray<Category> ();
private int stamp = (int) Random.next_int ();
@@ -98,15 +118,24 @@ public class ShortcutsModel : GLib.Object, TreeModel {
var dvd = new DeviceShortcut ("Blank DVD+RW Disc", "media-optical-dvd", false);
devices.items.add (dvd);
+ var separator = new SeparatorCategory ();
+ categories.add (separator);
+
var places = new Category ("Places");
categories.add (places);
var home = new SystemShortcut ("ochosi", "user-home");
places.items.add(home);
- var desktop = new SystemShortcut ("desktop", "user-desktop");
+ var desktop = new SystemShortcut ("Desktop", "user-desktop");
places.items.add (desktop);
+ var music = new SystemShortcut ("Music", "folder-music");
+ places.items.add (music);
+
+ separator = new SeparatorCategory ();
+ categories.add (separator);
+
var network = new Category ("Network");
categories.add (network);
@@ -122,7 +151,7 @@ public class ShortcutsModel : GLib.Object, TreeModel {
}
public int get_n_columns () {
- return 3;
+ return ColumnTypes.length;
}
public Type get_column_type (int index) {
@@ -163,9 +192,16 @@ public class ShortcutsModel : GLib.Object, TreeModel {
}
public TreePath get_path (TreeIter iter) {
- /* TODO implement me */
- assert (false);
- return new TreePath ();
+ int category_index = (int) iter.user_data;
+ int item_index = (int) iter.user_data2;
+
+ TreePath path = new TreePath ();
+
+ path.append_index (category_index);
+ if (item_index >= 0)
+ path.append_index (item_index);
+
+ return path;
}
public void get_value (TreeIter iter, int column, out Value value) {
@@ -179,20 +215,43 @@ public class ShortcutsModel : GLib.Object, TreeModel {
assert (item_index < category.items.length);
if (item_index < 0) {
- if (column == Column.NAME)
- value = "<b>" + category.name + "</b>";
- else
+ switch (column) {
+ case Column.NAME:
+ value = "<span size='large' weight='medium' color='#353535'>" + category.name + "</span>";
+ break;
+ case Column.SEPARATOR:
+ bool is_separator = category is SeparatorCategory;
+ value = is_separator;
+ break;
+ case Column.SENSITIVE:
+ bool is_sensitive = !(category is SeparatorCategory);
+ value = is_sensitive;
+ break;
+ default:
value = Value (ColumnTypes[column]);
+ break;
+ }
} else {
var item = category.items.get (item_index);
assert (item != null);
- if (column == Column.NAME)
+ switch (column) {
+ case Column.NAME:
value = item.name;
- else if (column == Column.ICON) {
+ break;
+ case Column.ICON:
value = item.icon;
- } else
+ break;
+ case Column.SEPARATOR:
+ value = false;
+ break;
+ case Column.SENSITIVE:
+ value = true;
+ break;
+ default:
value = Value (ColumnTypes[column]);
+ break;
+ }
}
}
@@ -336,25 +395,277 @@ public class ShortcutsModel : GLib.Object, TreeModel {
-public class CellRendererFlexibleIcon : CellRendererPixbuf {
+public class ShortcutRenderer : CellRenderer {
+ public Icon icon { get; set; }
+ public string markup { get; set; }
+ public uint spacing { get; set; default = 6; }
+ public IconSize icon_size { get; set; default = IconSize.MENU; }
+
+ private Widget widget { get; private set; }
+ private Pango.Layout layout { get; set; }
+
+ private void update_widget (Widget widget) {
+ /* disconnect from old widget */
+
+ /* connect to new widget */
+
+ /* set the widget property */
+ this.widget = widget;
- public override void get_size (Widget widget, Gdk.Rectangle? cell_area,
- out int x_offset, out int y_offset,
- out int width, out int height)
+ if (widget != null) {
+ /* allocate a new pango layout for this widget */
+ var context = widget.get_pango_context ();
+ layout = new Pango.Layout (context);
+
+ /* disable automatic text directio to use the directioned specified by GTK+ */
+ layout.set_auto_dir (false);
+
+ /* we don't want to interpret line separators in file names */
+ layout.set_single_paragraph_mode (true);
+ } else {
+ layout = null;
+ }
+ }
+
+ public override void get_size (Widget widget,
+ Gdk.Rectangle? cell_area,
+ out int x_offset,
+ out int y_offset,
+ out int width,
+ out int height)
{
- if (gicon != null) {
- x_offset = 0;
- y_offset = 0;
- width = 16;
- height = 16;
+ /* update the widget and regenerate the pango layout */
+ update_widget (widget);
+
+ /* compute icon and text size */
+ int icon_width;
+ int icon_height;
+ int text_width;
+ int text_height;
+ compute_icon_size (widget, out icon_width, out icon_height);
+ compute_text_size (widget, cell_area, out text_width, out text_height);
+
+ /* compute total width */
+ width = ((icon_width > 0) ? (icon_width + (int) spacing) : 0) + text_width;
+
+ /* compute total height */
+ height = int.max (icon_height, text_height);
+
+ /* compute offset depending on the widget direction */
+ if (cell_area != null) {
+ x_offset = (int) ((widget.get_direction () == TextDirection.RTL ? 1.0 - xalign : xalign) * (cell_area.width - width));
+ x_offset = int.max (x_offset, 0) + (int) xpad;
+
+ y_offset = (int) (yalign * (cell_area.height - height));
+ y_offset = int.max (y_offset, 0) + (int) ypad;
} else {
x_offset = 0;
y_offset = 0;
- width = 0;
- height = 0;
}
+
+ /* add padding */
+ width += (int) xpad * 2;
+ height += (int) ypad * 2;
}
+ private void compute_icon_size (Widget widget,
+ out int width,
+ out int height)
+ {
+ /* initialize the width and height */
+ width = 0;
+ height = 0;
+
+ /* compute the size of the icon */
+ if (icon != null) {
+ if (!Gtk.icon_size_lookup (icon_size, out width, out height)) {
+ width = 16;
+ height = 16;
+ }
+ }
+ }
+
+ private void compute_text_size (Widget widget,
+ Gdk.Rectangle? cell_area,
+ out int width,
+ out int height)
+ {
+ /* TODO this is dirty, we should really use pango here and take
+ * ellipsizing into account */
+
+ layout.set_width (-1);
+ layout.set_wrap (Pango.WrapMode.CHAR);
+ layout.set_markup (markup, -1);
+
+ /* calculate the real text dimension */
+ layout.get_pixel_size (out width, out height);
+ }
+
+ public override void render (Gdk.Window window,
+ Widget widget,
+ Gdk.Rectangle background_area,
+ Gdk.Rectangle cell_area,
+ Gdk.Rectangle expose_area,
+ CellRendererState flags)
+ {
+ /* update the widget and regenerate the pango layout */
+ update_widget (widget);
+
+ /* determine the state */
+ StateType state = StateType.NORMAL;
+ if ((flags & CellRendererState.SELECTED) != 0) {
+ if (widget.has_focus)
+ state = StateType.SELECTED;
+ else
+ state = StateType.ACTIVE;
+ } else if ((flags & CellRendererState.PRELIT) != 0
+ && widget.state == StateType.PRELIGHT)
+ {
+ state = StateType.PRELIGHT;
+ } else {
+ if (widget.state == StateType.INSENSITIVE)
+ state = StateType.INSENSITIVE;
+ else
+ state = StateType.NORMAL;
+ }
+
+ if (widget.get_direction () == TextDirection.RTL) {
+ int x = cell_area.x;
+
+ /* render the text */
+ render_text (window, widget, background_area, cell_area, expose_area, state, x, out x);
+
+ if (icon != null) {
+ x += (int) spacing;
+
+ /* render the icon */
+ render_icon (window, widget, background_area, cell_area, expose_area, state, x, out x);
+ }
+ } else {
+ int x = 0;
+
+ if (icon != null) {
+ /* compute the size of the icon */
+ int icon_width;
+ int icon_height;
+ compute_icon_size (widget, out icon_width, out icon_height);
+
+ /* compute icon area */
+ var icon_area = Gdk.Rectangle() {
+ x = cell_area.x + x,
+ y = cell_area.y,
+ width = int.min (cell_area.width - x, icon_width),
+ height = int.min (cell_area.height, icon_height)
+ };
+
+ /* render the icon */
+ render_icon (window, widget, background_area, icon_area, expose_area, state, x, out x);
+
+ x += (int) spacing;
+ }
+
+ /* compute text area */
+ var text_area = Gdk.Rectangle() {
+ x = cell_area.x + x,
+ y = cell_area.y,
+ width = cell_area.width - x,
+ height = cell_area.height
+ };
+
+ /* render the text */
+ render_text (window, widget, background_area, text_area, expose_area, state, x, out x);
+ }
+ }
+
+ private void render_icon (Gdk.Window window,
+ Widget widget,
+ Gdk.Rectangle background_area,
+ Gdk.Rectangle cell_area,
+ Gdk.Rectangle expose_area,
+ StateType state,
+ int x,
+ out int new_x)
+ {
+ if (icon == null)
+ return;
+
+ Gdk.Pixbuf pixbuf = null;
+
+ /* load the icon */
+ if (icon is ThemedIcon) {
+ var icon_theme = IconTheme.get_default ();
+ var icon_info = icon_theme.lookup_by_gicon (icon, icon_size, IconLookupFlags.USE_BUILTIN);
+ if (icon_info != null) {
+ try {
+ pixbuf = icon_info.load_icon ();
+ } catch (Error e) {
+ }
+ }
+ } else if (icon is LoadableIcon) {
+ }
+
+ if (pixbuf == null)
+ return;
+
+ var icon_area = Gdk.Rectangle ();
+ var draw_area = Gdk.Rectangle ();
+
+ /* determine the real icon size */
+ icon_area.width = pixbuf.width;
+ icon_area.height = pixbuf.height;
+
+ /* scale down on demand */
+ if (icon_area.width > cell_area.width || icon_area.height > cell_area.height) {
+ pixbuf = pixbuf.scale_simple (cell_area.width, cell_area.height, Gdk.InterpType.BILINEAR);
+ icon_area.width = pixbuf.width;
+ icon_area.height = pixbuf.height;
+ }
+
+ icon_area.x = cell_area.x + (cell_area.width - icon_area.width) / 2;
+ icon_area.y = cell_area.y + (cell_area.height - icon_area.height) / 2;
+
+ new_x = x + icon_area.width;
+
+ if (expose_area.intersect (icon_area, out draw_area)) {
+ Gdk.draw_pixbuf (window, widget.style.black_gc, pixbuf,
+ draw_area.x - icon_area.x,
+ draw_area.y - icon_area.y,
+ draw_area.x,
+ draw_area.y,
+ draw_area.width,
+ draw_area.height,
+ Gdk.RgbDither.NORMAL,
+ 0, 0);
+ }
+ }
+
+ private void render_text (Gdk.Window window,
+ Widget widget,
+ Gdk.Rectangle background_area,
+ Gdk.Rectangle cell_area,
+ Gdk.Rectangle expose_area,
+ StateType state,
+ int x,
+ out int new_x)
+ {
+ layout.set_width (-1);
+ layout.set_wrap (Pango.WrapMode.CHAR);
+ layout.set_markup (markup, -1);
+
+ /* calculate the real text dimension */
+ int width;
+ int height;
+ layout.get_pixel_size (out width, out height);
+
+ int x_offset = 0;
+ int y_offset = 0;
+
+ Gtk.paint_layout (widget.style, window, state, true,
+ expose_area, widget, "cellrenderertext",
+ cell_area.x + x_offset + (int) xpad,
+ cell_area.y + y_offset + (int) ypad,
+ layout);
+ }
}
@@ -375,23 +686,43 @@ public class ShortcutsView : Frame {
model = new ShortcutsModel ();
view = new TreeView ();
+ view.set_border_width (6);
view.set_model (model);
- view.set_headers_visible (true);
- view.set_level_indentation (-16);
+ view.set_headers_visible (false);
+ view.set_level_indentation (-14);
scrollwin.add (view);
view.show ();
- var icon_renderer = new CellRendererFlexibleIcon ();
+ view.get_selection ().set_select_function (select_row);
- var name_renderer = new CellRendererText ();
+ var shortcut_renderer = new ShortcutRenderer ();
var column = new TreeViewColumn ();
- column.set_title ("Name");
- column.pack_start (icon_renderer, false);
- column.set_attributes (icon_renderer, "gicon", ShortcutsModel.Column.ICON);
- column.pack_start (name_renderer, true);
- column.set_attributes (name_renderer, "markup", ShortcutsModel.Column.NAME);
+ column.set_title ("Shortcut");
+ column.pack_start (shortcut_renderer, true);
+ column.set_attributes (shortcut_renderer,
+ "icon", ShortcutsModel.Column.ICON,
+ "markup", ShortcutsModel.Column.NAME,
+ "sensitive", ShortcutsModel.Column.SENSITIVE);
view.append_column(column);
+
+ view.expand_all ();
+ }
+
+ private bool select_row (TreeSelection selection,
+ TreeModel model,
+ TreePath path,
+ bool currently_selected)
+ {
+ TreeIter iter;
+
+ if (model.get_iter (out iter, path)) {
+ bool is_separator = false;
+ model.get (iter, ShortcutsModel.Column.SEPARATOR, out is_separator, -1);
+ return !is_separator;
+ } else {
+ return false;
+ }
}
}
More information about the Xfce4-commits
mailing list