Commit 42b5114f authored by Jody Goldberg's avatar Jody Goldberg

- Move some math functions from utils to mathfuncs.

- Beautify the scrollbar tooltips a bit and move some of their utility
  routines into gnumeric-utility.
- Add width/height tooltips on col/row resize.
- Fix bug that would loose the end of resize event when the cursor had
  not moved.
parent 18cda29f
1999-10-07 Jody Goldberg <jgoldberg@home.com>
1999-10-08 Jody Goldberg <jgoldberg@home.com>
* src/main.c : Add new command line parameter. --debug_ole
* src/item-bar.c (item_bar_event) : Use item_bar_end_resize.
(item_bar_end_resize) : Cleare resizing flag even if when have not
moved and created a resize marker.
1999-10-07 Miguel de Icaza <miguel@gnu.org>
......@@ -9,6 +11,28 @@
1999-10-07 Jody Goldberg <jgoldberg@home.com>
* src/item-bar.c : Add tooltip to show width/height during resize.
* src/gnumeric-util.[ch] (gnumeric_create_tooltip,
gnumeric_position_tooltip) : New functions.
* src/mathfunc.[ch], src/utils.[ch] : Move random_01, random_normal,
and gpow10 from utils -> mathfunc.
* src/goal-seek.c : Add an include for mathfunc.h
* src/sheet-view.c (sheet_view_new) : Init tip to NULL.
(set_tip_label) : Delete.
(create_tip) : Poach the inards and use as a starting point for
gnumeric_create_tooltip.
(position_tooltip) : Rename and move to gnumeric-utils.
* src/main.c : Add new command line parameter. --debug_ole
* src/sheet.c (sheet_col_size_fit) : Handle empty col by using the
default width.
(sheet_row_size_fit) : Handle empty row by using the default height.
* src/item-grid.c (item_grid_find_row,
item_grid_find_col) : Return a value in the overflow case.
......
......@@ -10,6 +10,7 @@ Michael:
Jody:
* Some Optimization.
* Enhance row/col insert/delete, cell shift, and cell cut/paste.
* Some eye candy.
Jon K Hellan:
* Dialog improvements.
......
1999-10-07 Jody Goldberg <jgoldberg@home.com>
1999-10-08 Jody Goldberg <jgoldberg@home.com>
* src/main.c : Add new command line parameter. --debug_ole
* src/item-bar.c (item_bar_event) : Use item_bar_end_resize.
(item_bar_end_resize) : Cleare resizing flag even if when have not
moved and created a resize marker.
1999-10-07 Miguel de Icaza <miguel@gnu.org>
......@@ -9,6 +11,28 @@
1999-10-07 Jody Goldberg <jgoldberg@home.com>
* src/item-bar.c : Add tooltip to show width/height during resize.
* src/gnumeric-util.[ch] (gnumeric_create_tooltip,
gnumeric_position_tooltip) : New functions.
* src/mathfunc.[ch], src/utils.[ch] : Move random_01, random_normal,
and gpow10 from utils -> mathfunc.
* src/goal-seek.c : Add an include for mathfunc.h
* src/sheet-view.c (sheet_view_new) : Init tip to NULL.
(set_tip_label) : Delete.
(create_tip) : Poach the inards and use as a starting point for
gnumeric_create_tooltip.
(position_tooltip) : Rename and move to gnumeric-utils.
* src/main.c : Add new command line parameter. --debug_ole
* src/sheet.c (sheet_col_size_fit) : Handle empty col by using the
default width.
(sheet_row_size_fit) : Handle empty row by using the default height.
* src/item-grid.c (item_grid_find_row,
item_grid_find_col) : Return a value in the overflow case.
......
......@@ -11,6 +11,7 @@
#include "gnumeric.h"
#include "gnumeric-util.h"
#include "style.h"
#include "color.h"
void
gnumeric_no_modify_array_notice (Workbook *wb)
......@@ -229,3 +230,52 @@ gnumeric_popup_menu (GtkMenu *menu, GdkEventButton *event)
gnumeric_auto_kill_popup_menu_on_hide (menu);
gtk_menu_popup (menu, NULL, NULL, 0, NULL, event->button, event->time);
}
GtkWidget *
gnumeric_create_tooltip (void)
{
GtkWidget *tip, *label, *frame;
static GtkRcStyle*rc_style = NULL;
if (rc_style == NULL) {
int i;
rc_style = gtk_rc_style_new();
for (i = 5; --i >= 0 ; ) {
rc_style->color_flags[i] = GTK_RC_BG;
color_alloc_name ("LightYellow", &rc_style->bg[i]);
}
}
tip = gtk_window_new (GTK_WINDOW_POPUP);
if (rc_style != NULL)
gtk_widget_modify_style (tip, rc_style);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
label = gtk_label_new ("");
gtk_container_add (GTK_CONTAINER (tip), frame);
gtk_container_add (GTK_CONTAINER (frame), label);
return label;
}
void
gnumeric_position_tooltip (GtkWidget *tip, int horizontal)
{
GtkRequisition req;
int x, y;
gtk_widget_size_request (tip, &req);
gdk_window_get_pointer (NULL, &x, &y, NULL);
if (horizontal){
x = x - req.width/2;
y = y - req.height - 20;
} else {
x = x - req.width - 20;
y = y - req.height/2;
}
gtk_widget_set_uposition (gtk_widget_get_toplevel (tip), x, y);
}
......@@ -23,4 +23,10 @@ char *x11_font_change_component (const char *fontname, int idx, const ch
void gnumeric_auto_kill_popup_menu_on_hide (GtkMenu *menu);
void gnumeric_popup_menu (GtkMenu *menu, GdkEventButton *event);
/*
* Some tool tip support code.
*/
void gnumeric_position_tooltip (GtkWidget *tip, int horizontal);
GtkWidget * gnumeric_create_tooltip (void);
#endif /* GNUMERIC_GNUMERIC_UTIL_H */
......@@ -17,7 +17,7 @@
#include <math.h>
#include "goal-seek.h"
#include "gnumeric.h"
#include "utils.h"
#include "mathfunc.h"
/*
* This value should be comfortably within the relative precision of a float_t.
......
......@@ -11,6 +11,7 @@
#include "gnumeric.h"
#include "gnumeric-util.h"
#include "style.h"
#include "color.h"
void
gnumeric_no_modify_array_notice (Workbook *wb)
......@@ -229,3 +230,52 @@ gnumeric_popup_menu (GtkMenu *menu, GdkEventButton *event)
gnumeric_auto_kill_popup_menu_on_hide (menu);
gtk_menu_popup (menu, NULL, NULL, 0, NULL, event->button, event->time);
}
GtkWidget *
gnumeric_create_tooltip (void)
{
GtkWidget *tip, *label, *frame;
static GtkRcStyle*rc_style = NULL;
if (rc_style == NULL) {
int i;
rc_style = gtk_rc_style_new();
for (i = 5; --i >= 0 ; ) {
rc_style->color_flags[i] = GTK_RC_BG;
color_alloc_name ("LightYellow", &rc_style->bg[i]);
}
}
tip = gtk_window_new (GTK_WINDOW_POPUP);
if (rc_style != NULL)
gtk_widget_modify_style (tip, rc_style);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
label = gtk_label_new ("");
gtk_container_add (GTK_CONTAINER (tip), frame);
gtk_container_add (GTK_CONTAINER (frame), label);
return label;
}
void
gnumeric_position_tooltip (GtkWidget *tip, int horizontal)
{
GtkRequisition req;
int x, y;
gtk_widget_size_request (tip, &req);
gdk_window_get_pointer (NULL, &x, &y, NULL);
if (horizontal){
x = x - req.width/2;
y = y - req.height - 20;
} else {
x = x - req.width - 20;
y = y - req.height/2;
}
gtk_widget_set_uposition (gtk_widget_get_toplevel (tip), x, y);
}
......@@ -23,4 +23,10 @@ char *x11_font_change_component (const char *fontname, int idx, const ch
void gnumeric_auto_kill_popup_menu_on_hide (GtkMenu *menu);
void gnumeric_popup_menu (GtkMenu *menu, GdkEventButton *event);
/*
* Some tool tip support code.
*/
void gnumeric_position_tooltip (GtkWidget *tip, int horizontal);
GtkWidget * gnumeric_create_tooltip (void);
#endif /* GNUMERIC_GNUMERIC_UTIL_H */
......@@ -306,73 +306,3 @@ parse_cell_name_list (Sheet *sheet,
free (buf);
return cells;
}
/*
* Conservative random number generator. The result is (supposedly) uniform
* and between 0 and 1. (0 possible, 1 not.) The result should have about
* 64 bits randomness.
*/
double
random_01 (void)
{
#ifdef HAVE_RANDOM
int r1, r2;
r1 = random () & 2147483647;
r2 = random () & 2147483647;
return (r1 + (r2 / 2147483648.0)) / 2147483648.0;
#elif defined (HAVE_DRAND48)
return drand48 ();
#else
/* We try to work around lack of randomness in rand's lower bits. */
int prime = 65537;
int r1, r2, r3, r4;
g_assert (RAND_MAX > ((1 << 12) - 1));
r1 = (rand () ^ (rand () << 12)) % prime;
r2 = (rand () ^ (rand () << 12)) % prime;
r3 = (rand () ^ (rand () << 12)) % prime;
r4 = (rand () ^ (rand () << 12)) % prime;
return (r1 + (r2 + (r3 + r4 / (double)prime) / prime) / prime) / prime;
#endif
}
/*
* Generate a N(0,1) distributed number.
*/
double
random_normal (void)
{
return qnorm (random_01 (), 0, 1);
}
/*
* Generate 10^n being careful not to overflow
*/
float_t
gpow10 (int n)
{
float_t res = 1.0;
float_t p;
const int maxn = 300;
if (n >= 0) {
p = 10.0;
n = (n > maxn) ? maxn : n;
} else {
p = 0.1;
/* Note carefully that we avoid overflow. */
n = (n < -maxn) ? maxn : -n;
}
while (n > 0) {
if (n & 1) res *= p;
p *= p;
n >>= 1;
}
return res;
}
......@@ -28,8 +28,4 @@ gint gnumeric_strcase_equal (gconstpointer v, gconstpointer v2);
guint32 g_date_serial (GDate *date);
GDate *g_date_new_serial (guint32 serial);
double random_01 (void);
double random_normal (void);
float_t gpow10 (int n);
#endif /* GNUMERIC_UTILS_H */
......@@ -13,6 +13,7 @@
#include "item-bar.h"
#include "item-debug.h"
#include "utils.h"
#include "gnumeric-util.h"
#include "selection.h"
/* Marshal forward declarations */
......@@ -50,6 +51,9 @@ item_bar_destroy (GtkObject *object)
bar = ITEM_BAR (object);
if (bar->tip)
gtk_object_unref (GTK_OBJECT (bar->tip));
if (GTK_OBJECT_CLASS (item_bar_parent_class)->destroy)
(*GTK_OBJECT_CLASS (item_bar_parent_class)->destroy)(object);
}
......@@ -392,6 +396,39 @@ get_col_from_pos (ItemBar *item_bar, int pos)
return i;
}
static void
colrow_tip_setlabel (ItemBar *item_bar, gboolean const is_vertical, int const size)
{
if (item_bar->tip) {
char buffer [20 + sizeof (long) * 4];
if (is_vertical)
snprintf (buffer, sizeof (buffer), _("Height: %.2f"), size *.75);
else
snprintf (buffer, sizeof (buffer), _("Width: %.2f"), size / 7.5);
gtk_label_set_text (GTK_LABEL (item_bar->tip), buffer);
}
}
static void
item_bar_end_resize (ItemBar *item_bar, int new_size)
{
if (item_bar->resize_guide) {
if (new_size > 0)
gtk_signal_emit (GTK_OBJECT (item_bar),
item_bar_signals [SIZE_CHANGED],
item_bar->resize_pos,
new_size);
gtk_object_destroy (item_bar->resize_guide);
item_bar->resize_guide = NULL;
}
if (item_bar->tip) {
gtk_widget_destroy (gtk_widget_get_toplevel (item_bar->tip));
item_bar->tip = NULL;
}
item_bar->start_selection = -1;
item_bar->resize_pos = -1;
}
#define convert(c,sx,sy,x,y) gnome_canvas_w2c (c,sx,sy,x,y)
static gint
......@@ -401,14 +438,13 @@ item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
GnomeCanvas *canvas = item->canvas;
ItemBar *item_bar = ITEM_BAR (item);
int pos, start, element, x, y;
int resizing;
resizing = ITEM_BAR_RESIZING (item_bar);
gboolean const resizing = ITEM_BAR_RESIZING (item_bar);
gboolean const is_vertical = (item_bar->orientation == GTK_ORIENTATION_VERTICAL);
switch (e->type){
case GDK_ENTER_NOTIFY:
convert (canvas, e->crossing.x, e->crossing.y, &x, &y);
if (item_bar->orientation == GTK_ORIENTATION_VERTICAL)
if (is_vertical)
pos = y;
else
pos = x;
......@@ -417,7 +453,7 @@ item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
case GDK_MOTION_NOTIFY:
convert (canvas, e->motion.x, e->motion.y, &x, &y);
if (item_bar->orientation == GTK_ORIENTATION_VERTICAL)
if (is_vertical)
pos = y;
else
pos = x;
......@@ -443,6 +479,7 @@ item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
item_bar->resize_width = npos;
colrow_tip_setlabel (item_bar, is_vertical, item_bar->resize_width);
resize_guide = GNOME_CANVAS_ITEM (item_bar->resize_guide);
points = item_bar_get_line_points (canvas, item_bar, pos);
......@@ -473,14 +510,14 @@ item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
case GDK_BUTTON_PRESS:
convert (canvas, e->button.x, e->button.y, &x, &y);
if (item_bar->orientation == GTK_ORIENTATION_VERTICAL)
if (is_vertical)
pos = y;
else
pos = x;
cri = is_pointer_on_division (item_bar, pos, &start, &element);
if (item_bar->orientation == GTK_ORIENTATION_VERTICAL){
if (is_vertical) {
if (element > SHEET_MAX_ROWS-1)
break;
} else {
......@@ -499,22 +536,28 @@ item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
item_bar->resize_pos = element;
item_bar->resize_start_pos = start - cri->pixels;
item_bar->resize_width = cri->pixels;
if (item_bar->tip == NULL) {
item_bar->tip = gnumeric_create_tooltip ();
colrow_tip_setlabel (item_bar, is_vertical, item_bar->resize_width);
gnumeric_position_tooltip (item_bar->tip, !is_vertical);
gtk_widget_show_all (gtk_widget_get_toplevel (item_bar->tip));
}
} else if (e->button.button == 3){
Sheet *sheet = item_bar->sheet_view->sheet;
gboolean const is_col = (item_bar->orientation != GTK_ORIENTATION_VERTICAL);
/* If the selection does not contain the current row/col
* then clear the selection and add it.
*/
if (!selection_contains_colrow (sheet, element, is_col))
if (!selection_contains_colrow (sheet, element, !is_vertical))
gtk_signal_emit (GTK_OBJECT (item),
item_bar_signals [SELECTION_CHANGED],
element, e->button.state | GDK_BUTTON1_MASK);
if (is_col)
item_grid_popup_menu (sheet, e, element, 0);
else
if (is_vertical)
item_grid_popup_menu (sheet, e, 0, element);
else
item_grid_popup_menu (sheet, e, element, 0);
} else {
item_bar->start_selection = element;
gnome_canvas_item_grab (item,
......@@ -536,19 +579,12 @@ item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
break;
sheet = item_bar->sheet_view->sheet;
if (item_bar->orientation == GTK_ORIENTATION_VERTICAL)
if (is_vertical)
new_size = sheet_row_size_fit (sheet, item_bar->resize_pos);
else
new_size = sheet_col_size_fit (sheet, item_bar->resize_pos);
if (new_size == 0)
break;
gtk_signal_emit (GTK_OBJECT (item),
item_bar_signals [SIZE_CHANGED],
item_bar->resize_pos,
new_size);
item_bar->resize_pos = -1;
item_bar_end_resize (item_bar, new_size);
}
break;
......@@ -556,17 +592,9 @@ item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
if (e->button.button == 3)
break;
if (resizing && item_bar->resize_guide){
gtk_signal_emit (GTK_OBJECT (item),
item_bar_signals [SIZE_CHANGED],
item_bar->resize_pos,
item_bar->resize_width);
item_bar->resize_pos = -1;
gtk_object_destroy (item_bar->resize_guide);
item_bar->resize_guide = NULL;
}
/* This will only happen if we did not double click */
gnome_canvas_item_ungrab (item, e->button.time);
item_bar->start_selection = -1;
item_bar_end_resize (item_bar, item_bar->resize_width);
break;
default:
......@@ -592,6 +620,7 @@ item_bar_init (ItemBar *item_bar)
item_bar->orientation = GTK_ORIENTATION_VERTICAL;
item_bar->resize_pos = -1;
item_bar->start_selection = -1;
item_bar->tip = NULL;
}
static void
......
......@@ -31,6 +31,9 @@ typedef struct {
int dragging : 1;
/* Tip for scrolling */
GtkWidget *tip;
/* Where the selection started */
int start_selection;
} ItemBar;
......
......@@ -4,6 +4,8 @@
* Authors:
* Ross Ihaka (See also note below.)
* Morten Welinder <terra@diku.dk>
* Miguel de Icaza (miguel@gnu.org)
* Jukka-Pekka Iivonen (iivonen@iki.fi)
*/
/*
......@@ -3864,3 +3866,73 @@ double bessel_k(double x, double alpha, double expo)
free(bk);
return x;
}
/*
* Conservative random number generator. The result is (supposedly) uniform
* and between 0 and 1. (0 possible, 1 not.) The result should have about
* 64 bits randomness.
*/
double
random_01 (void)
{
#ifdef HAVE_RANDOM
int r1, r2;
r1 = random () & 2147483647;
r2 = random () & 2147483647;
return (r1 + (r2 / 2147483648.0)) / 2147483648.0;
#elif defined (HAVE_DRAND48)
return drand48 ();
#else
/* We try to work around lack of randomness in rand's lower bits. */
int prime = 65537;
int r1, r2, r3, r4;
g_assert (RAND_MAX > ((1 << 12) - 1));
r1 = (rand () ^ (rand () << 12)) % prime;
r2 = (rand () ^ (rand () << 12)) % prime;
r3 = (rand () ^ (rand () << 12)) % prime;
r4 = (rand () ^ (rand () << 12)) % prime;
return (r1 + (r2 + (r3 + r4 / (double)prime) / prime) / prime) / prime;
#endif
}
/*
* Generate a N(0,1) distributed number.
*/
double
random_normal (void)
{
return qnorm (random_01 (), 0, 1);
}
/*
* Generate 10^n being careful not to overflow
*/
float_t
gpow10 (int n)
{
float_t res = 1.0;
float_t p;
const int maxn = 300;
if (n >= 0) {
p = 10.0;
n = (n > maxn) ? maxn : n;
} else {
p = 0.1;
/* Note carefully that we avoid overflow. */
n = (n < -maxn) ? maxn : -n;
}
while (n > 0) {
if (n & 1) res *= p;
p *= p;
n >>= 1;
}
return res;
}
......@@ -108,4 +108,8 @@ double qbinom (double x, double n, double p);
/* ------------------------------------------------------------------------- */
double random_01 (void);
double random_normal (void);
float_t gpow10 (int n);
#endif
......@@ -16,6 +16,7 @@
#include "selection.h"
#include "sheet-object.h"
#include "item-cursor.h"
#include "gnumeric-util.h"
#include "utils.h"
#include "selection.h"
......@@ -343,70 +344,32 @@ button_select_all (GtkWidget *the_button, SheetView *sheet_view)
}
static void
set_tip_label (SheetView *sheet_view, char *format, GtkAdjustment *adj, int horizontal)
vertical_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
if (sheet_view->tip) {
char buffer [20 + sizeof (long) * 4];
if (horizontal)
snprintf (buffer, sizeof (buffer), format, col_name (adj->value));
else
snprintf (buffer, sizeof (buffer), format, (int) adj->value + 1);
snprintf (buffer, sizeof (buffer), _("Row: %d"), (int) adj->value + 1);
gtk_label_set_text (GTK_LABEL (sheet_view->tip), buffer);
}
static void
vertical_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
if (sheet_view->tip)
set_tip_label (sheet_view, _("Row: %d"), adj, 0);
}
}
static void
horizontal_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
if (sheet_view->tip)
set_tip_label (sheet_view, _("Column: %s"), adj, 1);
}
static GtkWidget *
create_tip (void)
{
GtkWidget *tip, *label;
tip = gtk_window_new (GTK_WINDOW_POPUP);
label = gtk_label_new ("");
gtk_container_add (GTK_CONTAINER (tip), label);
return label;
}
static void
position_tooltip (SheetView *sheet_view, int horizontal)
{
GtkRequisition req;
int x, y;
gtk_widget_size_request (sheet_view->tip, &req);
gdk_window_get_pointer (NULL, &x, &y, NULL);
if (horizontal){
x = x - req.width/2;
y = y - req.height - 20;
} else {
x = x - req.width - 20;
y = y - req.height/2;
if (sheet_view->tip) {
char buffer [20 + sizeof (long) * 4];
snprintf (buffer, sizeof (buffer), _("Column: %s"), col_name (adj->value));
gtk_label_set_text (GTK_LABEL (sheet_view->tip), buffer);
}
gtk_widget_set_uposition (gtk_widget_get_toplevel (sheet_view->tip), x, y);
}