[ghex] layout-manager: rework cpl algorithms and clean up
- From: Logan Rathbone <larathbone src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ghex] layout-manager: rework cpl algorithms and clean up
- Date: Sat, 11 Dec 2021 16:19:27 +0000 (UTC)
commit 25322b0c8051b7359b3fd2a1d076c0e89cc8ec72
Author: Logan Rathbone <poprocks gmail com>
Date: Sat Dec 11 02:31:06 2021 -0500
layout-manager: rework cpl algorithms and clean up
I think this finally right about where I want it now. We've done away
with the 75/25 fixed ratio which didn't work at all for larger
groupsizes.
src/gtkhex-layout-manager.c | 261 +++++++++++++++++++++++---------------------
1 file changed, 137 insertions(+), 124 deletions(-)
---
diff --git a/src/gtkhex-layout-manager.c b/src/gtkhex-layout-manager.c
index 3075f85..697afa5 100644
--- a/src/gtkhex-layout-manager.c
+++ b/src/gtkhex-layout-manager.c
@@ -28,16 +28,10 @@
* than to use config.h. Don't change unless you change code in gtkhex.c as well.
*/
#define OFFSETS_CPL 8
-#define HEX_RATIO 0.75
-#define ASCII_RATIO 0.25
struct _GtkHexLayout {
GtkLayoutManager parent_instance;
- GtkWidget *offets;
- GtkWidget *hex;
- GtkWidget *ascii;
-
guint char_width;
guint group_type;
@@ -209,70 +203,37 @@ gtk_hex_layout_measure (GtkLayoutManager *layout_manager,
*natural = natural_size;
}
-/* Helper */
-static void
-get_cpl_from_ascii_width (GtkHexLayout *self, GtkWidget *widget, int width)
-{
- int hex_cpl, ascii_cpl;
- int real_width;
- GtkStyleContext *context;
- GtkBorder margins, padding;
-
- /* Need to grab padding and margins - can't assume that the number of
- * ascii chars that can be crammed into the widget is equal to its width
- * divided by the width of a single character.
- */
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_get_margin (context, &margins);
- gtk_style_context_get_padding (context, &padding);
-
- real_width = width -
- margins.left - margins.right - padding.left - padding.right;
-
- ascii_cpl = real_width / self->char_width;
- while (ascii_cpl % self->group_type != 0)
- --ascii_cpl;
-
- hex_cpl = ascii_cpl * 2;
- hex_cpl += ascii_cpl / self->group_type;
-
- self->hex_cpl = hex_cpl;
- self->cpl = ascii_cpl;
-}
-
static void
gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
GtkWidget *widget,
- int width,
- int height,
- int baseline)
+ int full_width,
+ int full_height,
+ int baseline) /* N/A */
{
GtkHexLayout *self = GTK_HEX_LAYOUT (layout_manager);
- GtkHexLayoutChild *child_info;
GtkWidget *child;
gboolean have_hex = FALSE;
gboolean have_ascii = FALSE;
-#define BASE_ALLOC {.x = 0, .y = 0, .width = 0, .height = height}
+#define BASE_ALLOC {.x = 0, .y = 0, .width = 0, .height = full_height}
GtkAllocation off_alloc = BASE_ALLOC;
GtkAllocation hex_alloc = BASE_ALLOC;
GtkAllocation asc_alloc = BASE_ALLOC;
- GtkAllocation scr_alloc = BASE_ALLOC;
+ GtkAllocation sbar_alloc = BASE_ALLOC;
#undef BASE_ALLOC
- GtkAllocation tmp_alloc = {0};
+
+ int avail_width = full_width;
+ GtkWidget *hex = NULL, *ascii = NULL, *offsets = NULL, *scrollbar = NULL;
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
- GtkRequisition child_req = { .width = 0, .height = 0 };
+ GtkHexLayoutChild *child_info;
+ /* If it's invisible, etc., this should fail. */
if (! gtk_widget_should_layout (child))
continue;
- /* Get preferred size of the child widget */
-
- gtk_widget_get_preferred_size (child, &child_req, NULL);
-
/* Setup allocation depending on what column we're in.
* This loop is run through again once we obtain some initial values. */
@@ -281,109 +242,161 @@ gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
switch (child_info->column)
{
- case OFFSETS_COLUMN:
- {
- GtkStyleContext *context = gtk_widget_get_style_context (child);
- GtkBorder margins, padding, borders;
-
- gtk_style_context_get_margin (context, &margins);
- gtk_style_context_get_padding (context, &padding);
- gtk_style_context_get_border (context, &borders);
-
- off_alloc.width = OFFSETS_CPL * self->char_width +
- margins.left + margins.right +
- padding.left + padding.right +
- borders.left + borders.right;
- }
+ case OFFSETS_COLUMN: offsets = child;
break;
-
- case HEX_COLUMN:
- have_hex = TRUE;
+ case HEX_COLUMN: hex = child;
break;
-
- case ASCII_COLUMN:
- have_ascii = TRUE;
+ case ASCII_COLUMN: ascii = child;
break;
-
- case SCROLLBAR_COLUMN:
- scr_alloc.x = width - child_req.width;
- scr_alloc.width = child_req.width;
- scr_alloc.height = height;
+ case SCROLLBAR_COLUMN: scrollbar = child;
break;
-
+ /* We won't test for this each loop. */
default:
g_error ("%s: Programmer error. Requested column invalid.",
__func__);
break;
}
}
-
- for (child = gtk_widget_get_first_child (widget);
- child != NULL;
- child = gtk_widget_get_next_sibling (child))
+
+ /* Order doesn't really matter for the offsets & scrollbar columns since
+ * they're essentially fixed, so let's do those first.
+ */
+ if (offsets)
{
- GtkRequisition child_req = { .width = 0, .height = 0 };
+ GtkBorder margins, padding, borders;
+ GtkStyleContext *context = gtk_widget_get_style_context (offsets);
- if (! gtk_widget_should_layout (child))
- continue;
+ gtk_style_context_get_margin (context, &margins);
+ gtk_style_context_get_padding (context, &padding);
+ gtk_style_context_get_border (context, &borders);
- /* Get preferred size of the child widget */
+ /* nb: offsets always goes at x coordinate 0 so just leave it as it's
+ * zeroed out anyway. */
- gtk_widget_get_preferred_size (child, &child_req, NULL);
+ off_alloc.width = OFFSETS_CPL * self->char_width +
+ margins.left + margins.right +
+ padding.left + padding.right +
+ borders.left + borders.right;
- /* Setup allocation depending on what column we're in. */
+ avail_width -= off_alloc.width;
+ }
- child_info = GTK_HEX_LAYOUT_CHILD(
- gtk_layout_manager_get_layout_child (layout_manager, child));
+ if (scrollbar)
+ {
+ GtkRequisition req = { .width = 0, .height = 0 };
+ gtk_widget_get_preferred_size (scrollbar, &req, NULL);
- switch (child_info->column)
- {
- case OFFSETS_COLUMN:
- tmp_alloc = off_alloc;
- break;
+ /* It's always going to be its full width and will always be to the far
+ * right, so just plop it there.
+ */
+ sbar_alloc.x = full_width - req.width;
+ sbar_alloc.width = req.width;
+ sbar_alloc.height = full_height;
- case HEX_COLUMN:
- hex_alloc.width = width - off_alloc.width;
- hex_alloc.width -= scr_alloc.width;
+ avail_width -= sbar_alloc.width;
+ }
- if (have_ascii) {
- hex_alloc.width *= HEX_RATIO;
- hex_alloc.x += off_alloc.width;
- }
- tmp_alloc = hex_alloc;
- break;
+ /* Let's measure ascii next, as hex's width is essentially locked to it, if
+ * it's visible. Since hex and ascii are both drawing areas, they both
+ * default to preferring a width of 0, so we have to measure completely.
+ */
+ if (ascii)
+ {
+ int ascii_max_width;
- case ASCII_COLUMN:
- asc_alloc.x += off_alloc.width;
- asc_alloc.width = width;
- asc_alloc.width -= off_alloc.width;
- asc_alloc.width -= scr_alloc.width;
+ /* Use width of offsets (if any) as baseline for x posn of ascii and
+ * go from there.
+ */
+ asc_alloc.x = off_alloc.width;
- if (have_hex) {
- asc_alloc.width *= ASCII_RATIO;
- asc_alloc.x += (width - off_alloc.width - scr_alloc.width)
- * HEX_RATIO;
- }
- tmp_alloc = asc_alloc;
+ ascii_max_width = asc_alloc.width =
+ full_width - off_alloc.width - sbar_alloc.width;
- get_cpl_from_ascii_width (self, child, asc_alloc.width);
+ if (hex)
+ {
+ GtkStyleContext *context;
+ int tot_cpl, hex_cpl, ascii_cpl;
+ int max_width_left = ascii_max_width;
+
+ GtkBorder hex_margins, hex_padding;
+ GtkBorder asc_margins, asc_padding;
+
+ context = gtk_widget_get_style_context (hex);
+ gtk_style_context_get_margin (context, &hex_margins);
+ gtk_style_context_get_padding (context, &hex_padding);
+
+ max_width_left = max_width_left -
+ hex_margins.left - hex_margins.right -
+ hex_padding.left - hex_padding.right;
+
+ context = gtk_widget_get_style_context (ascii);
+ gtk_style_context_get_margin (context, &asc_margins);
+ gtk_style_context_get_padding (context, &asc_padding);
+
+ max_width_left = max_width_left -
+ asc_margins.left - asc_margins.right -
+ asc_padding.left - asc_padding.right;
+
+ tot_cpl = max_width_left / self->char_width;
+
+ /* Calculate how many hex vs. ascii characters can be stuffed
+ * on one line.
+ */
+ ascii_cpl = 0;
+ do {
+ if (ascii_cpl % self->group_type == 0 &&
+ tot_cpl < self->group_type * 3)
+ break;
+
+ ++ascii_cpl;
+ tot_cpl -= 3; /* 2 for hex disp, 1 for ascii disp */
+
+ if (ascii_cpl % self->group_type == 0) /* just ended a group */
+ tot_cpl--;
+ }
+ while (tot_cpl > 0);
- break;
+ hex_cpl = ascii_cpl * 2 + ascii_cpl / self->group_type;
- case SCROLLBAR_COLUMN:
- tmp_alloc = scr_alloc;
- break;
+ asc_alloc.width = ascii_cpl * self->char_width;
+ hex_alloc.width = max_width_left - asc_alloc.width;
- default:
- g_error ("%s: Programmer error. The requested column is invalid.",
- __func__);
- break;
+ /* add back the margins and padding prev. deducted from values.
+ */
+ asc_alloc.width += asc_margins.left + asc_margins.right +
+ asc_padding.left + asc_padding.right;
+
+ hex_alloc.width += hex_margins.left + hex_margins.right +
+ hex_padding.left + hex_padding.right;
+
+ hex_alloc.x = off_alloc.width;
+ asc_alloc.x = hex_alloc.x + hex_alloc.width;
+
+ self->hex_cpl = hex_cpl;
+ self->cpl = ascii_cpl;
}
+ }
- gtk_widget_size_allocate (child,
- &tmp_alloc,
- -1); /* baseline, or -1 */
+ /* Already determined what to do if have ascii and hex together */
+ if (hex && !ascii)
+ {
+ hex_alloc.x = off_alloc.width;
+ hex_alloc.width = full_width - off_alloc.width - sbar_alloc.width;
+
+ /* TODO - get_cpl_from_hex_width ()
+ self->hex_cpl = ???
+ self->cpl = ???
+ */
}
+
+ if (offsets)
+ gtk_widget_size_allocate (offsets, &off_alloc, -1);
+ if (scrollbar)
+ gtk_widget_size_allocate (scrollbar, &sbar_alloc, -1);
+ if (hex)
+ gtk_widget_size_allocate (hex, &hex_alloc, -1);
+ if (ascii)
+ gtk_widget_size_allocate (ascii, &asc_alloc, -1);
}
static GtkSizeRequestMode
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]